Python3 笔记
安装
Windows 10
在官网上直接下载安装包, https://www.python.org/downloads/windows/
对应64位win10三个安装包:embeddable, executable和web-based,第一个是最小化用于嵌入其他项目的,第二个是正常安装包带pip,第三个是只下载安装引导文件,通过网络安装。对应Windows XP的最高版本只到3.4
Python3在Windows下默认是安装到用户目录下,C:\Users\Milton\AppData\Local\Programs\Python\Python38
在windows10下将python路径添加到path会遇到一个问题, 在命令行中执行python时, windows会启动microsoft store, 这是因为windows10里面设置了python的关联,
1. 点击开始, 输入"Manage App Execution Aliases", 打开这个设置面板, 在里面找到App Install - python3.exe并关掉
2. 如果上面的无效, 则从用户的path里删掉 C:\Users\Username\AppData\Local\Microsoft\WindowsApps\ 这一项
PyCharm 2020.1 下面import xml.dom一直标红不知道怎么回事,后来查到是PC的bug,https://youtrack.jetbrains.com/issue/PY-41791 , 解决方法为
Replace xml directory in <INSTALLATION_FOLDER>\plugins\python(-ce)\helpers\typeshed\stdlib\2and3\ with xml from https://github.com/python/typeshed/tree/master/stdlib/2and3/xml
Ubuntu18.04 Python3环境
默认python3已经安装了, 可能是安装其他应用的时候因为依赖关系安装的.
安装pip3, 先sudo apt update 一下, apt-cache search python3-pip 看看有没有, 如果没有的话检查一下/etc/apt/sources.list 是否正确, 可以参考以下的source.list
deb http://cn.archive.ubuntu.com/ubuntu/ bionic main restricted deb http://cn.archive.ubuntu.com/ubuntu/ bionic-updates main restricted deb http://cn.archive.ubuntu.com/ubuntu/ bionic universe deb http://cn.archive.ubuntu.com/ubuntu/ bionic-updates universe deb http://cn.archive.ubuntu.com/ubuntu/ bionic multiverse deb http://cn.archive.ubuntu.com/ubuntu/ bionic-updates multiverse deb http://cn.archive.ubuntu.com/ubuntu/ bionic-backports main restricted universe multiverse deb http://security.ubuntu.com/ubuntu bionic-security main restricted deb http://security.ubuntu.com/ubuntu bionic-security universe deb http://security.ubuntu.com/ubuntu bionic-security multiverse
然后通过 sudo apt install python3-pip 安装
安装库依赖
命令为
pip install 包名
使用镜像
pip install -r requirements.txt -i https://pypi.douban.com/simple --trusted-host=pypi.douban.com
可用的镜像还有 https://mirrors.ustc.edu.cn/pypi/web/simple/
常用的package有: pymongo, pyyaml, requests等
requirements.txt为pip导出的包列表,导出方法为
# 列出已安装的包 pip freeze # or pip list # 导出requirements.txt pip freeze > requirements.txt
PyCharm安装和配置
下载pycharm压缩包, 解压至 /opt/jetbrains, sudo chown为root:root, 运行 bin/pycharm.sh, 根据提示完成配置
版本2020.2默认不安装桌面图标, 在启动对话框右下角点击Configuration, 点击安装desktop entry, 不勾选all user.
环境配置
Settings->Project [Your project], Python Interpreter, 添加系统自带的python, 如果已经安装了pip, 会自动带入, 这两项使用系统自带的
其他的库包, 都在PyCharm的Terminal模块里通过 pip install 安装, 会安装到项目目录下 venv/lib/pythonX.X/site-packages 和 venv/lib64/pythonX.X/site-packages , 这样可以隔离项目之间的版本影响, 相应的会浪费一些硬盘空间.
常用语法
符号
// 双斜杠表示地板除, 即先做除法/, 然后向下取整floor. 至少有一方是float时结果为float, 两方都是int时结果为int
合并两个Dictionary
x = {'aa':1, 'bb':2, 'cc':3} y = {'aa':5, 'xx':6, 'yy':7} z = {**x, **y} x.update(y) print(x) # 输出 {'aa': 5, 'bb': 2, 'cc': 3, 'xx': 6, 'yy': 7} {'aa': 5, 'bb': 2, 'cc': 3, 'xx': 6, 'yy': 7}
两种方法都可以实现dictionary合并, 前者不会修改原先两个dictionary的值
逻辑判断
# 空, 非空 if (x is None) if (not x is None) # dictionary是否包含某key if ('name' in x.keys()) if (not 'name' in x.keys())
字符串操作
# 赋值时会自动合并 y = 'Hello ' 'World' print(y) # substring, 截取从0到100(左边include, 右边exclude)的子串, slice方式不会报数组越界 print(y[0:3]) # Hel print(y[0:100]) # Hello World print(y[-2:]) # ld
用%号做字符串赋值
# 单个字符串 msg = "he is %s ,his hobby is play" %"xiaoming" # 多个值 msg = "he is %s ,his hobby is %s" %("xiaoming","play") # 百分号转义, 小数限位 tpl="percent %.2f %%" %78.7658943256 #键值对形式传字典 tpl="i am %(name)s age %(age)d" %{"name":"小明","age":"18"} ''' %c 字符及其ASCII码 %s 字符串 %d 有符号整数(十进制) %u 无符号整数(十进制) %o 无符号整数(八进制) %x 无符号整数(十六进制) %X 无符号整数(十六进制大写字符) %e 浮点数字(科学计数法) %E 浮点数字(科学计数法,用E代替e) %f 浮点数字(用小数点符号) %g 浮点数字(根据值的大小采用%e或%f) %G 浮点数字(类似于%g) %p 指针(用十六进制打印值的内存地址) %n 存储输出字符的数量放进参数列表的下一个变量中 '''
用format()做字符串赋值
# 按顺序赋值 tp1 = "i am {}, age {}, {}".format("seven", 18, 'alex') # 指定序号赋值 tp3 = "i am {0}, age {1}, really {0}".format("seven", 18) # 指定名称赋值, 右侧结构为字典 tp5 = "i am {name}, age {age}, really {name}".format(name="seven", age=18) # 指定类型赋值 a1 = "numbers: {:b},{:o},{:d},{:x},{:X}, {:%},{:c}".format(15, 15, 15, 15, 15, 15.87623,65) # 指定 序号 + 类型 a2 = "numbers: {0:b},{0:o},{0:d},{0:x},{0:X}, {0:%},{1:c}".format(15,65) # 指定 名称 + 类型 a3 = "numbers: {num:b},{num:o},{num:d},{num:x},{num:X}, {num:%},{cc:c}".format(num=15,cc=65) ''' 可用类型 ” 字符串类型 “的参数 s,格式化字符串类型数据 空白,未指定类型,则默认是None,同s “ 整数类型 ”的参数 b,将10进制整数自动转换成2进制表示然后格式化 c,将10进制整数自动转换为其对应的unicode字符 d,十进制整数 o,将10进制整数自动转换成8进制表示然后格式化; x,将10进制整数自动转换成16进制表示然后格式化(小写x) X,将10进制整数自动转换成16进制表示然后格式化(大写X) “ 浮点型或小数类型 ”的参数 e, 转换为科学计数法(小写e)表示,然后格式化; E, 转换为科学计数法(大写E)表示,然后格式化; f , 转换为浮点型(默认小数点后保留6位)表示,然后格式化; F, 转换为浮点型(默认小数点后保留6位)表示,然后格式化; g, 自动在e和f中切换 G, 自动在E和F中切换 %,显示百分比(默认显示小数点后6位) '''
.
List, Tuple 和 Set
tuple是不可变的, 用括号赋值(也可以不用)
# tuple的赋值 tup1 = 'str1', tup2 = ('str1',) tup3 = 'str1', 'str2' tup4 = ('str1', 'str2')
tup5 = ([1,2,3], 'aa', 12345)
list是可变的, list的操作与String很像, [a:b]实际上是对原数组的复制, 下面的代码就避免了操作原列表造成无限循环
for w in words[:]: # Loop over a slice copy of the entire list. if len(w) > 6: words.insert(0, w)
list可以使用[[...]] 直接指定下标获得一个副本子序列, 里面的[...]也可以是表达式生成的list
# 直接下标获取子序列copy iris_X_train = iris_X[[0,1,2,3]] # 通过list表达式指定 iris_X_train = iris_X[indices[:-10]]
.对list做运算, 都是直接对list内的元素作运算, 例如, 求得list中每一个元素的平方, 最后得到的也是同样元素个数的list
# 求方差 square_error = (iris_y_result - iris_y_test)**2
yield关键字
在函数末尾,yield用于代替return返回一个generator。关于yield的用法在这篇文章里讲的很好 https://stackoverflow.com/questions/231767/what-does-the-yield-keyword-do , 简单的说,就是在面对一个巨大的列表,例如处理一大批文件,接收未知数量的数据时,可以返回一个generator给调用方来做iteration。这时候要用到yield关键字,此时返回的并不是列表,而是一个可以iterate的generator对象。
常用内置函数
bin(x) 将一个整数转换为二进制值的字符串, 以 0b 开头(如果是负数则是 -0b)
enumerate() 用于将一个可遍历的数据对象(如列表、元组或字符串)组合为一个索引序列, 同时列出数据和数据下标, 一般用在 for 循环当中, 可以指定下标开始值, 如 enumerate(seasons, start=1)
id(object) 获取对象的全局唯一标识值. 注意, 如果两个对象的生命周期没有重叠, 可能会使用相同的对象id值
input(prompt) 用于命令行执行中, 暂停并弹出输入提示, 返回值是输入的字符串
len(x) 计算长度, 可以作用于序列或集合, a sequence (such as a string, bytes, tuple, list, or range) or a collection (such as a dictionary, set, or frozen set).
list(iterable) 创建一个和iterable数组的元素一样次序也一样的list
map(func, list) 接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回
zip(*iterables) 合并参数中的多个iterable里的元素, 按原顺序, 不要求元素个数一致, 但是结果中只包含最短那个的个数
常用模块
HTTP请求. Requests模块
使用手册 http://docs.python-requests.org/zh_CN/latest/api.html
使用举例
import requests def requestGet(url, encoding='UTF-8', tout=20, retries=10): count = 0 while True: count += 1 if (count > retries): print('Exceed retry limit') return None try: response = requests.get(url, timeout=tout) response.encoding = encoding return response.text except requests.ReadTimeout: print('ReadTimeout') continue except ConnectionError: print('ConnectionError') continue except requests.RequestException: print('RequestException') continue
注意: 抓取GB2312网页时, encoding建议使用GB18030, 避免部分特殊文字乱码
在Requests中保持session信息
session = requests.session() # 然后就可以用session来进行各种http请求 session.headers.update({ 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:68.0) Gecko/20100101 Firefox/68.0', 'Referer': config.base_url + '/default/', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8' }) #print(session.headers) #print(session.cookies.get_dict()) post_data = {'id':user_name,'passwd': user_pass} rs = session.post(config.base_url + '/bbslogin1203.php', post_data, proxies=config.proxies) print(session.cookies.get_dict())
在Reqeusts中使用代理
如果使用socks5代理,需要安装pysocks (pip3 install pysocks)
response = session.get(url, timeout=tout, proxies=dict( http='socks5://user:pass@host:port', https='socks5://user:pass@host:port'))
各种代理的参数格式
# SOCKS5 proxy for HTTP/HTTPS proxiesDict = { 'http' : "socks5://1.2.3.4:1080", 'https' : "socks5://1.2.3.4:1080" } # SOCKS4 proxy for HTTP/HTTPS proxiesDict = { 'http' : "socks4://1.2.3.4:1080", 'https' : "socks4://1.2.3.4:1080" } # HTTP proxy for HTTP/HTTPS proxiesDict = { 'http' : "1.2.3.4:1080", 'https' : "1.2.3.4:1080" }
Mongodb 操作. Pymongo模块
使用举例
import pymongo # 连接mongodb client = pymongo.MongoClient('172.17.0.2', 27017) # 选择db db = client.db_1 # 选择collection tb_user = db['user'] # count total = tb_user.count_documents({}) # select one dummy = tb_user.find_one({'_id': name}) # select all, and sort allusers = tb_user.find().sort('posts', -1) # insert or save tb_user.save(user)
Collection级别的操作
# 创建索引 collection_demo.create_index([('field1', pymongo.ASCENDING)])
检查索引是否存在, 存在则删除索引
indexes = board_col.list_indexes() for index in indexes: print(index) print(index['name']) if (index['name'] == 'author_text_created_at_-1'): board_col.drop_index('author_text_created_at_-1') # 创建联合索引 board_col.create_index([('author', pymongo.TEXT),('created_at', pymongo.DESCENDING)])
如果要在python中直接执行mongo 命令, 需要使用 eval(), 例如以下的语句用于将多个同构的collection合并到同一个collection
for board in boards: tb_current = rbcommon.db['deb_' + str(board['_id'])] if (not tb_current is None): current_total = tb_current.find().count() print(str(board['_id']) + ', ' + board['name'] + ', ' + board['name2'] + ', ' + str(current_total)) rbcommon.db.eval('db.deb_'+ str(board['_id']) +'.find({}).forEach(function(u) {db.deb_all.save(u);})')
count_documents()的坑
对于数据量很大的collection, 尽量不要使用这个方法, 因为这个方法实际上需要遍历所有documents, 会非常慢. 可以使用 estimated_document_count() 这个方法, 这个是从collection的metadata中读取的缓存的documents数量, 如果此时collection正在写入, 可能会与实际数量有出入.
YAML配置文件读取
import yaml # 获取当前文件的路径, 注意: 是common.py路径, 不带slash, 不是引用common的文件的路径, # 可以用 os.path.realpath(__file__) 测试 rootPath = os.path.dirname(__file__) print(rootPath) configPath = os.path.join(rootPath,'config.yml') print(configPath) with open(configPath, 'r') as ymlfile: cfg = yaml.load(ymlfile) # yaml会自动将长得像数字的值, 转换为数字类型. 下面是使用配置参数值的方式 mongoclient = pymongo.MongoClient(cfg['mongo']['host'], cfg['mongo']['port']) db = mongoclient[cfg['mongo']['db']] tb_section = db['section']
.
常见问题
循环中出现 pymongo.errors.CursorNotFound: cursor id xxx not found 错误
默认mongo server维护连接的时间窗口是十分钟, 默认单次从 server获取数据是101条或者 大于1M小于16M的数据, 所以默认情况下如果循环中的某步在10分钟内未能处理完数据, 则抛出异常. 解决办法为使用no_cursor_timeout = True 参数
allBoards = rbcommon.tb_board.find({}, no_cursor_timeout = True).sort('post_count', -1) for board in allBoards: # 0:through out mode, 1:increament mode readBoard(board)
在windows10下安装ahocorasick
命令是
pip install pyahocorasick
但是这个需要编译C++,如果没装Microsoft Visual C++会报以下错误
error: Microsoft Visual C++ 14.0 is required. Get it with "Build Tools for Visual Studio": https://visualstudio.microsoft.com/downloads/
这时候去这个网址下载Build Tools就可以了,安装的时候实际运行的是Visual Studio Installer,要勾选Visual Studio Build Tools里面的C++ Build Tools,这会下载1.2GB的文件,安装后占用4.xG的空间。然后再运行上面的pip install 就可以正常安装了。