Iawen's Blog

我喜欢这样自由的随手涂鸦, 因为我喜欢风......

Python由荷兰数学和计算机科学研究学会的吉多·范罗苏姆 于1990 年代初设计, 作为一门叫做ABC语言的替代品。Python提供了高效的高级数据结构, 还能简单有效地面向对象编程。Python语法和动态类型, 以及解释型语言的本质, 使它成为多数平台上写脚本和快速开发应用的编程语言, 随着版本的不断更新和语言新功能的添加, 逐渐被用于独立的、大型项目的开发。

1. 安装Python3

1.1 安装依赖

yum install openssl-devel bzip2-devel expat-devel gdbm-devel readline-devel sqlite-devel 

# 3.7版本需要一个新的包libffi-devel, 安装此包之后再次进行编译安装即可。
# Failed to build these modules: _ctypes
yum install libffi-devel -y

1.2 下载python3.6编译安装

到python官网下载https://www.python.org 最新版源码, 使用make altinstall, 如果使用make install, 在系统中将会有两个不同版本的Python在/usr/bin/目录中。这将会导致很多问题, 而且不好处理。

wget https://www.python.org/ftp/python/3.6.0/Python-3.6.0.tgz
tar -xzvf Python-3.6.0.tgz -C  /tmp
cd  /tmp/Python-3.6.0/
./configure --prefix=/usr/local
make
make altinstall

# 启用pip3: 
python -m ensurepip

1.3 更改/usr/bin/python链接

cd /usr/bin
mv  python python.backup
ln -s /usr/local/bin/python3.6 /usr/bin/python
ln -s /usr/local/bin/python3.6 /usr/bin/python3

1.4 Centos: 更改yum脚本的python依赖

cd/usr/bin
lsyum*
yumyum-config-manageryum-debug-restoreyum-groups-manager
yum-builddepyum-debug-dumpyumdownloader 

# 更改以上文件头为
#!/usr/bin/python 改为 #!/usr/bin/python2
 
# 修改gnome-tweak-tool配置文件
vi /usr/bin/gnome-tweak-tool 
#!/usr/bin/python 改为 #!/usr/bin/python2
 
# 修改urlgrabber配置文件
vi /usr/libexec/urlgrabber-ext-down
#!/usr/bin/python 改为 #!/usr/bin/python2

2. Python 常用操作

2.1 查看本地Python所有模块

pydoc moduls         # 或者的交互式命令下
>>> help("modules")  # 更详细

查看函数的详细参数列表

import inspect
print(inspect.getfullargspec(function_name))

2.2 解释器里查看帮助

不带参数调用help()函数,就会进入在线帮助文档, 输入q或者quit就会返回到解释器. 如果知道自己的需要,就可以将模块名或数据类型作为参数调用help()函数,比如:

help(str)
help(dict.update) //假定该模块已导入

只关注某数据类型提供了哪些属性(比如方法)就已经足够,这一信息可以使用dir()函数获取, 比如:

dir(str)

2.3 常用数据结构

  • 列表和双端队列: list, collections.deque
  • 字典: {}, collections.defaultdic, collections.Counter
  • 集: set, 并集(union)/交集(intersection)/差集(difference)
  • 堆: heapq, queue.PriorityQueue(线程和进程安全)
    • heapify, heappush, heappop
      其元素插入操作和最大值提取操作的时间复杂度都为O(log(N))
  • 字典树: 也称前缀树, patricia.trie, datrie, marisa-trie

3. Python 常用模块

3.1 re: 正则表达式模块

正则表达式, 核心步骤就是先使用re.compile() 编译正则表达式字符串, 然后使用match(), findall() 或者finditer()等方法。

3.1.1 主要函数

  • match / search
  • group / groups
  • findall / finditer findall返回一个列表, finditer与findall类似, 但更节省内存的变态
  • sub / subn 实现搜索和替换。sub返回一个替换后的字符串。subn则返回一个2-tuple, 包含替换后的字符串, 以及替换的次数
>>> re.sub('X', 'Mr. Smith', 'attn:X\n\nDear X,\n')
'attn:Mr. Smith\n\nDear Mr. Smith,\n'
>>> re.subn('X', 'Mr. Smith', 'attn:X\n\nDear X,\n')
('attn:Mr. Smith\n\nDear Mr. Smith,\n', 2)

3.1.2 扩展符号(?iLmsux)

re.I/IGNORECASE 忽略大小写
re.M/MULTILINE 多行混合
re.S/DOTALL 表明点号(.)能够用来表示\n符号
re.X/VERBOSE 允许用户通过抑制在表达式中使用空白符
re.L/LOCALE
re.U/UNICODE

(?:) 以及(?p) 和 (?p=name)

>>> re.search(r'\((?P<areacode>\d{3})\) (?P<prefix>\d{3})-(?:\d{4})', '(800) 555-1212').groupdict()
{'areacode': '800', 'prefix': '555'}

(?=…) 以及 (?!…)
前者是正向前视断言, 后者是负向前视断言

>>> re.findall(r'\w+(?= van Rossum)', '''
... Guido van Rossum
... Tim Peters
... Just van Rossum
... ''')
['Guido', 'Just']
>>> re.findall(r'(?m)^\s+(?!noreply|postmaster)(\w+)', '''
... sales@phptr.com
... postmaster@phptr.com
... eng@phptr.com
... noreply@phptr.com
... ''')
['sales', 'eng']

3.2 常用网络P模块

ftplib FTP协议
httplib HTTP 协议
nntplib NNTP协议
smtplib SMTP 协议
poplib POP协议
imaplib IMAP协议

>>> from ftplib import FTP
>>> f = FTP('ftp1.linuxidc.com')
>>> f.login('ftp1.linuxidc.com', 'www.linuxidc.com')
'230-(bbsftp v2.8) [Cache 1322868Sec/300Sec Num (3)]\n\n230 User logged in, proceed.'
>>> f.dir()

>>> from poplib import POP3
>>> p = POP3('pop.163.com')
>>> p.user('913221@163.com')
b'+OK core mail'
>>> p.pass_('xxxxxxxxxxxxxxxxx')
b'+OK 12 message(s) [390075 byte(s)]'
>>> p.stat()
(12, 390075)
>>> rsp, msg, siz = p.retr(12)
>>> rsp,siz
(b'+OK 8512 octets', 8512)
>>> for line in msg:
...     print(line)
... 
b'Received: from quickmail.51job.com (unknown [61.129.48.189])'

>>> from imaplib import IMAP4    
>>> s = IMAP4('imap.163.com')
>>> s.login('913221@163.com', 'xxx')
('OK', [b'LOGIN completed'])
>>> rsp, msgs = s.select('INBOX', True)
>>> rsp
'NO'

3.3 线程模块

_thread
threading
mutliprocessing
subprocess
queue
mutex
concurrent.futures

3.4 数据库

3.4.1 Django和数据库

http://docs.djangoproject.com/en/dev/topics/install/#data-base-installation

3.4.2 PyMySQL

3.4.3 SQLite3

>>> import sqlite3
>>> cxn = sqlite3.connect('/home/learn/db/sqlite3_test') 
>>> cur = cxn.cursor()
>>> cur.execute('DROP TABLE users')
>>> cur.execute('CREATE TABLE users(login VARCHAR(8), userid INTEGER)')
>>> cur.execute('INSERT INTO users VALUES("john", 100)')
>>> cur.execute('INSERT INTO users VALUES("jane", 110)')
>>> cur.execute('SELECT * FROM users')
>>> for user in cur.fetchall():
... print(user)
... 
('john', 100)
('jane', 110)
>>> cur.close()
>>> cxn.commit()
>>> cxn.close()

3.5 URL相关模块

urlparse
urllib
urllib3
Python2 中有 urllib、urlparse、urllib2, 以及其他内容。在Python3中, 所有相关模块都整合进了一个名为urllib的单一包中。

>>> import urllib
>>> dir(urllib)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__', 'error', 'parse', 'request', 'response']
>>> dir(urllib.parse)
['DefragResult', 'DefragResultBytes', 'MAX_CACHE_SIZE', 'ParseResult', 'ParseResultBytes', 'Quoter', 'ResultBase', 'SplitResult', 'SplitResultBytes', '_ALWAYS_SAFE', '_ALWAYS_SAFE_BYTES', '_DefragResultBase', '_NetlocResultMixinBase', '_NetlocResultMixinBytes', '_NetlocResultMixinStr', '_ParseResultBase', '_ResultMixinBytes', '_ResultMixinStr', '_SplitResultBase', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_asciire', '_coerce_args', '_decode_args', '_encode_result', '_hexdig', '_hextobyte', '_hostprog', '_implicit_encoding', '_implicit_errors', '_noop', '_parse_cache', '_portprog', '_safe_quoters', '_splitnetloc', '_splitparams', '_typeprog', 'clear_cache', 'collections', 'namedtuple', 'non_hierarchical', 'parse_qs', 'parse_qsl', 'quote', 'quote_from_bytes', 'quote_plus', 're', 'scheme_chars', 'splitattr', 'splithost', 'splitnport', 'splitpasswd', 'splitport', 'splitquery', 'splittag', 'splittype', 'splituser', 'splitvalue', 'sys', 'to_bytes', 'unquote', 'unquote_plus', 'unquote_to_bytes', 'unwrap', 'urldefrag', 'urlencode', 'urljoin', 'urlparse', 'urlsplit', 'urlunparse', 'urlunsplit', 'uses_fragment', 'uses_netloc', 'uses_params', 'uses_query', 'uses_relative']
>>> 
>>> import urllib.request, urllib.error, urllib.parse
>>> from base64 import encodestring
>>> URL = 'http://func.demo.com/demo'
>>> req = urllib.request.Request(URL)
>>> b64str = encodestring(bytes('%s:%s' % ('iawen', '123456'), 'utf-8'))[:-1]           
>>> req.add_header('Authorization', 'Basic %s' % b64str.decode('utf-8'))
>>> f = urllib.request.urlopen(req)
>>> print(f.readline().decode('utf-8'))
<!DOCTYPE html>

>>> f.close()
>>> 

3.6 构建WEB服务器应用

3.6.1 Django 和WEB服务器:

https://code.djangoproject.com/wiki/ServerArrangements

Python3上运行测试:

python -c "from http.server import CGIHTTPRequestHandler,test;test(CGIHTTPRequestHandler)"
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...

3.7 文本处理

3.7.1 csv

import csv
DATA = (
    (9, 'Web Clients and Servers', 'base62, urllib'),
    (10, 'Web programming: CGI & WSGI', 'cgi, time, wsgiref'),
    (13, 'Web Services', 'urllib, twython')
)
with open('bookdata.csv', 'w') as f:
    writer = csv.writer(f)
    for record in DATA:
        writer.writerow(record)

3.7.2 json(只理解Unicode字符串)

>>> dict(zip('abcde', range(5)))
{'a': 0, 'b': 1, 'c': 2, 'd': 3, 'e': 4}
>>> import json
>>> json.dumps(dict(zip('abcde', range(5))))
'{"a": 0, "b": 1, "c": 2, "d": 3, "e": 4}'
>>>

3.7.3 xml / xmlrpc

3.7.4 codecs

3.7.5 Unicode标准化: unicodedata

>>> s1 = 'Spicy Jalape\u00f1o' 
s1 'Spicy Jalapeño' 
>>> s2 = 'Spicy Jalapen\u0303o' 
s2 'Spicy Jalapeño' 
>>> s1 == s2 
False 
>>> import unicodedata 
>>> t1 = unicodedata.normalize('NFC', s1) 
>>> t2 = unicodedata.normalize('NFC', s2)  
>>> t1 == t2 True 
>>> print(ascii(t1))
'Spicy Jalape\xf1o' 
>>> print(ascii(t2)) 
'Spicy Jalape\xf1o'​

3.7.6 pickle模块

是将Python对象进行序列化(转换为字节序列, 或转换为字符串)的一种方法。
在Python 3.0中, pickle.HIGHEST_PROTOCOL 表示 protocol 3, 一种紧凑的二进制pickle 格式。
pickle.dump(self, fh, pickle.HIGHEST_PROTOCOL)
pickle 模块具有足够的自适应能力保存大多数自定义类的对象, 而不需要人工干预, 其前提是其私有的__dict__是picklable。

>>> import pickle
>>> t = [1, 2, 3]
>>> pickle.dumps(t)
b'\x80\x03]q\x00(K\x01K\x02K\x03e.'
>>> s = pickle.dumps(t)
>>> t2 = pickle.loads(s)
>>> t2
[1, 2, 3]
>>>

3.8 处理PDF的模块

wand,
pdf2image,
PyPDF2

3.9 数学函数: Math

math.log 计算以e为底的对数

3.10 海龟图形: turtle

import turtle
bob = turtle.Turtle()
bob.setpos(-350, -350)
bob.clear()
turtle.mainloop()

3.11 时间相关

3.11.1 time

>>> import time
>>> time.time()
1539576816.6211903
>>>

3.12 内建函数

3.12.1 zip

接收两个或或多个序列组, 并返回一个元组列表。zip对象是一个友善的迭代器。

>>> s = 'abc'
>>> t = [0, 1, 2]
>>> q = 'XYZ'
>>> for pair in zip(s, t, q):
... print(pair)
... 
('a', 0, 'X')
('b', 1, 'Y')
('c', 2, 'Z')

3.12.2 enumerate

返回一个枚举对象, 可基于一个包含若干个对的序列进行迭代, 每个对包含了索引号和给定序列中对应的元素。

>>> for idx, element in enumerate('abc'):
... print(idx, element)
... 
0 a
1 b
2 c

3.12.3 struct 模块

>>> import struct
>>> data = struct.pack("<2h", 11, -9);
>>> data
b'\x0b\x00\xf7\xff'
>>> items = struct.unpack("<2h", data)
>>> items
(11, -9)

struct 格式(基于字符串的长度):
比如, 给定字符串“en.wikipedia.org”, 则格式应该为“<H16s”(little-endian字节顺序, 2字节的无符号整数, 16字节的byte字符串。
< little-endian字节顺序
H 16位的无符号整数
其他, 如b/B(8位有/无符号)、h/H(16位有/无符号)、i/I(32位有/无符号)、q/Q(64位有/无符号)、f/d(32/64浮点)、?布尔、s(bytes/bytearray)

>>> str = b"en.wikipedia.org";
>>> format = "<H{0}s".format(len(str))
>>> data = struct.pack(format, len(str), str)
>>> data
b'\x10\x00en.wikipedia.org'
>>> item = struct.unpack(format, data)
>>> item
(16, b'en.wikipedia.org')

3.12.4 contextlib

上下文管理器, 只有在Python 3.0中, 使用contextlib.nested()才是必要的; 从Python 3.1 开始, 这一函数被废弃了, 因为Pyhton 3.1 可以在一个单独的with 语句中处理多个上下文管理器:

try:
    with open(source) as fin, open(target, "w") as fout:
        for line in fin:

3.12.5 functools、operator、itertools

for value in itertools.chain(data_list1, data_list2, data_list3):
    total += value

3.12.6 shelve模块

为DBM提供了一个wrapper。

3.12.7 configparser模块(ini文件)

文件名的匹配, 最好使用 glob 模块。
normalize() 第一参数指定字符串标准化的方式, NFC 表示字符应该是整体组成, 而NFD 表示字符应该分解为多个组合字符表示。

format和format_map() 的一个缺陷就是它们并不能很好的处理变量缺失的情况

3.12.8 collections

  • defaultdict
  • Counter

3.13 python重试库-tenacity

在与接口的通信过程中, 为了防止由于网络不稳定情况, 造成请求错误或者超时等问题, 或者其他不可控因素等造成功能性问题, 我们一般都会加入重试功能以增加代码的健壮性。

Tenacity 是一个 Apache 2.0 许可的通用重试库, 用 Python 编写, 用于简化向几乎任何事物添加重试行为的任务。

它具有如下特性:

  • 通用装饰器 API
  • 指定停止条件(即尝试次数限制)
  • 指定等待条件(即尝试之间的指数退避睡眠)
  • 自定义重试异常
  • 自定义对预期返回结果的重试
  • 重试协程
  • 使用上下文管理器重试代码块

4. Pyhton 进阶

4.1 性能分析

  • cprofile
    • 在命令行中使用:python -m cProfile -s tottime simul.py
    • 作为 Python 使用
from simul import benchmark
import cProfile

cProfile.run('benchmark()')
  • 在 IPython 中使用: %prun

  • line_profile: kernprof -l -v simul.py

  • memory_profiler: python -m memory_profiler simul.py
    为了减少内存消耗, 可以在类中使用__slots__, 这将避免实例的变量存储在内部字典中, 从而节省一些内存。缺点是:不能添加__slots__中没有指定的属性。

  • KCachegrind(QCachegrind): 以图形化方式显示各种剖析器生成的数据

  • timeit

4.1.1 py-spy

py-spy是一个 采样分析器(Statistical_profilers), 可以看到原生栈帧。

pip install py-spy

4.2 dis

dis(disassemble, 反汇编), 可以帮助了解代码如何转换为字节码

import dis
from xxx import yyy
dis.dis(yyy.func_name)

4.3 Numba和PyPy

对Python函数进行分析并将其直接编译成机器码。

5. 其他库

5.1 tqdm

Tqdm 是 Python 进度条库, 可以在 Python 长循环中添加一个进度提示信息。用户只需要封装任意的迭代器, 是一个快速、扩展性强的进度条工具库。

5.2 pyplot

matplotlib.pyplot模块提供了一个类似于MATLAB绘图方式的框架,可以使用其中的函数方便地绘制图形。

  • subplot函数:
    模块matplotlib.pyplot提供了函数matplotlib.pyplot.subplot()用来向当前窗口内添加一个子窗口对象: `matplotlib.pyplot.subplot(nrows, ncols, index)

  • imshow函数:
    模块matplotlib.pyplot提供了函数matplotlib.pyplot.imshow()用来显示图像: matplotlib.pyplot.imshow(X, cmap=None)
    plt.axis('off')表示关闭坐标轴的显示

参考:
python重试库-tenacity 使用指南
tqdm的使用