Skip to content

Commit c3e4787

Browse files
committed
add some
Change-Id: I0f00818768784f9a279a9108131d25a60d1f9dab
1 parent 45ccb76 commit c3e4787

17 files changed

+709
-68
lines changed

README.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ python的强大之处有很大的一方面在于它有各种各样非常强大
2525

2626
## [MySQLdb](content/MySQLdb.md)
2727

28+
## [pymysql](content/pymysql.md)
29+
2830
## [os](content/os.md)
2931

3032
## [shutil](content/shutil.md)
@@ -301,8 +303,18 @@ python的强大之处有很大的一方面在于它有各种各样非常强大
301303

302304
## [urllib2](content/urllib2.md)
303305

306+
## [ ] [urllib3](content/urllib3.md)
307+
308+
## [tempfile](content/tempfile.md)
309+
304310
## [httplib](content/httplib.md)
305311

312+
## [turtle](content/turtle.md)
313+
314+
## [py-spy](content/py-spy.md)
315+
316+
## [tqdm](content/tqdm.md)
317+
306318
## [tools](content/tools.md)
307319

308320
## [Other_thing](content/other_thing.md)

code/ast_eval_demo.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import ast
4+
5+
6+
if __name__ == '__main__':
7+
# 赋值操作不能有
8+
# print ast.literal_eval("a=1")
9+
# print eval("a=1")
10+
# a = 1
11+
# 加减乘除都不能有
12+
# print ast.literal_eval("1+1")
13+
# print eval("1+1")
14+
# print ast.literal_eval("1==1")
15+
print eval("1==1")
16+
print ast.literal_eval("1")
17+
print ast.literal_eval("None")
18+
# 连集合都不能有
19+
# print ast.literal_eval("{1,2,4}")
20+
# print ast.literal_eval("set([1])")
21+
# print ast.literal_eval("[1,2,{'1', 2, '2,3,4'}, [4,5,'6']]")
22+
# print [1,2,{'1', 2, '2,3,4'}, [4,5,'6']]
23+
print ast.literal_eval("[1,2,3,{2:3}]")
24+
# 连最终结果是一个list也不行
25+
# print ast.literal_eval("list([1,2,3])")
26+
print list([1, 2, 3])
27+
# print ast.literal_eval("[1,2+3]")
28+
# 复数可以有,负数也可以有
29+
print ast.literal_eval("1+2j")
30+
print ast.literal_eval("-2")
31+
# print ast.literal_eval("--2")
32+
# 正数就不行
33+
# print ast.literal_eval("+2")
34+
# print ast.literal_eval("++2")

code/ftplib_upload.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#coding=utf-8
1+
# coding=utf-8
22

33
import ftplib
44

code/pymysql_demo.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import pymysql
4+
5+
6+
connection = pymysql.connect(host='localhost',
7+
user='user',
8+
password='passwd',
9+
db='db',
10+
charset='utf8mb4',
11+
cursorclass=pymysql.cursors.DictCursor)
12+
13+
with connection.cursor() as cursor:
14+
sql = "INSERT INTO `users` (`email`, `password`) VALUES (%s, %s)"
15+
# 插入单行数据
16+
cursor.execute(sql, ('webmaster@python.org', 'very-secret'))
17+
# 插入多行数据
18+
cursor.executemany(sql, [
19+
('developer@python.org', 'medium-secret'),
20+
('support@python.org', 'low-secret')
21+
])
22+
23+
try:
24+
connection.commit()
25+
except Exception as e:
26+
print(repr(e))
27+
connection.rollback()
28+
29+
with connection.cursor() as cursor:
30+
sql = "SELECT `id`, `password` FROM `users` WHERE `email`=%s"
31+
cursor.execute(sql, ('webmaster@python.org',))
32+
result = cursor.fetchone()
33+
print(result)
34+
# 使用 DictCursor 可以将 fetch 到的结果转化成 dict 格式
35+
print(result['id'])
36+
37+
sql = "SELECT * from users;"
38+
cursor.execute(sql)
39+
result = cursor.fetchall()
40+
print([d['email'] for d in result])
41+
42+
# 最后别忘了关闭连接
43+
connection.close()

code/tempfile_demo.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# -*- coding: utf-8 -*-
2+
import tempfile
3+
4+
# create temp file
5+
print(tempfile.mktemp())
6+
7+
# create a temporary file and write some data to it
8+
fp = tempfile.TemporaryFile()
9+
fp.write(b'Hello world!')
10+
# read data from file
11+
fp.seek(0)
12+
print(fp.read())
13+
# close the file, it will be removed
14+
fp.close()
15+
16+
# create a temporary file using a context manager
17+
with tempfile.TemporaryFile() as fp:
18+
fp.write(b'Hello world!')
19+
fp.seek(0)
20+
print(fp.read())
21+
22+
# file is now closed and removed
23+
24+
# python 3
25+
# create a temporary directory using the context manager
26+
# with tempfile.TemporaryDirectory() as tmpdirname:
27+
# print('created temporary directory', tmpdirname)
28+
# directory and contents have been removed

code/tqdm_demo.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# coding=utf-8
2+
3+
import time
4+
from tqdm import trange, tqdm
5+
6+
for i in trange(10):
7+
time.sleep(0.1)
8+
9+
for i in tqdm(range(100)):
10+
time.sleep(0.1)

code/tqdm_example.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# coding=utf-8
2+
3+
import time
4+
import random
5+
from tqdm import tqdm
6+
7+
8+
count = 0
9+
total = 1024
10+
progress = tqdm(total=total, unit='B',unit_scale=True, desc='filename')
11+
12+
13+
while count < total:
14+
time.sleep(1)
15+
step = random.randrange(100)
16+
count += step
17+
progress.update(step)
18+
19+
progress.close()

code/udp_and_tcp_server.py

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import socket
4+
import select
5+
6+
host = '127.0.0.1'
7+
port = 8780
8+
9+
tcp_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
10+
tcp_server.bind((host, port))
11+
tcp_server.listen(5)
12+
13+
udp_server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
14+
udp_server.bind((host, port))
15+
16+
inputs = [tcp_server, udp_server]
17+
18+
if __name__ == '__main__':
19+
20+
print("Concurrent Listening on {}:{}, Press Ctrl-C to stop".format(host, port))
21+
22+
while True:
23+
rs, ws, es = select.select(inputs, [], [])
24+
for r in rs:
25+
if r is tcp_server:
26+
c, addr = tcp_server.accept()
27+
print('[TCP] Got connection from {}:{}'.format(*addr))
28+
inputs.append(c)
29+
elif r is udp_server:
30+
data, addr = udp_server.recvfrom(1024)
31+
print('[UDP] Got message: {} from {}:{}'.format(data, *addr))
32+
udp_server.sendto('[UDP] {}'.format(data), addr)
33+
else:
34+
try:
35+
data = r.recv(1024)
36+
disconnected = not data
37+
except socket.error:
38+
disconnected = True
39+
40+
if disconnected:
41+
print('[TCP] {}:{} disconnected.'.format(*r.getpeername()))
42+
inputs.remove(r)
43+
else:
44+
print('[TCP] Got message: {} from {}:{}'.format(data, *r.getpeername()))
45+
r.send('[TCP] {}'.format(data))

content/ast.md

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,99 @@ print astor.to_source(module)
155155
156156
```
157157

158-
有一个好消息是 3.9 开始支持 `ast.unparse` 反解析函数。
158+
有一个好消息是 Python 3.9 开始支持 `ast.unparse` 反解析函数。
159+
160+
### 安全的执行
161+
162+
在 Python 中有 `eval` 方法,但是一般如果直接调用 `eval` 执行的话,会有安全风险,可以试下 `ast.literal_eval` 进行安全的代码执行。
163+
164+
这个代码执行可以厉害了`୧(๑•̀◡•́๑)૭ `, 只能含有 Python 基本数据类型,数字,字符串,列表,字典,元组,布尔值,`None` 和复数。
165+
> 😂,复数?是不是突然觉得很突然,为什么会有复数?你是不是已经把复数是啥给忘了?`1+2j` 就是复数。
166+
167+
```python
168+
def literal_eval(node_or_string):
169+
"""
170+
Safely evaluate an expression node or a string containing a Python
171+
expression. The string or node provided may only consist of the following
172+
Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
173+
and None.
174+
"""
175+
_safe_names = {'None': None, 'True': True, 'False': False}
176+
if isinstance(node_or_string, basestring):
177+
node_or_string = parse(node_or_string, mode='eval')
178+
if isinstance(node_or_string, Expression):
179+
node_or_string = node_or_string.body
180+
def _convert(node):
181+
if isinstance(node, Str):
182+
return node.s
183+
elif isinstance(node, Num):
184+
return node.n
185+
elif isinstance(node, Tuple):
186+
return tuple(map(_convert, node.elts))
187+
elif isinstance(node, List):
188+
return list(map(_convert, node.elts))
189+
elif isinstance(node, Dict):
190+
return dict((_convert(k), _convert(v)) for k, v
191+
in zip(node.keys, node.values))
192+
elif isinstance(node, Name):
193+
if node.id in _safe_names:
194+
return _safe_names[node.id]
195+
elif isinstance(node, BinOp) and \
196+
isinstance(node.op, (Add, Sub)) and \
197+
isinstance(node.right, Num) and \
198+
isinstance(node.right.n, complex) and \
199+
isinstance(node.left, Num) and \
200+
isinstance(node.left.n, (int, long, float)):
201+
left = node.left.n
202+
right = node.right.n
203+
if isinstance(node.op, Add):
204+
return left + right
205+
else:
206+
return left - right
207+
raise ValueError('malformed string')
208+
return _convert(node_or_string)
209+
```
210+
211+
源码很简单,可以直接看代码,或者手动测试。
212+
213+
赋值操作不能用,加减乘除不能用,比较运算不能用,连集合都不能用。复数可以用,负数也可以,但是正数就不行。
214+
> 好消息是从 Python 3.2 开始支持集合。
215+
216+
```python
217+
# -*- coding: utf-8 -*-
218+
219+
import ast
220+
221+
222+
if __name__ == '__main__':
223+
# 赋值操作不能有
224+
# print ast.literal_eval("a=1")
225+
# print eval("a=1")
226+
# a = 1
227+
# 加减乘除都不能有
228+
# print ast.literal_eval("1+1")
229+
# print eval("1+1")
230+
# print ast.literal_eval("1==1")
231+
print eval("1==1")
232+
print ast.literal_eval("1")
233+
print ast.literal_eval("None")
234+
# 连集合都不能有
235+
# print ast.literal_eval("{1,2,4}")
236+
# print ast.literal_eval("set([1])")
237+
# print ast.literal_eval("[1,2,{'1', 2, '2,3,4'}, [4,5,'6']]")
238+
# print [1,2,{'1', 2, '2,3,4'}, [4,5,'6']]
239+
print ast.literal_eval("[1,2,3,{2:3}]")
240+
# 连最终结果是一个list也不行
241+
# print ast.literal_eval("list([1,2,3])")
242+
print list([1, 2, 3])
243+
# print ast.literal_eval("[1,2+3]")
244+
# 复数可以有,负数也可以有
245+
print ast.literal_eval("1+2j")
246+
print ast.literal_eval("-2")
247+
# print ast.literal_eval("--2")
248+
# 正数就不行
249+
# print ast.literal_eval("+2")
250+
# print ast.literal_eval("++2")
251+
252+
```
253+

content/marshmallow.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,11 @@ Deserializing,将一个 dict 或者 string 转化为对象,使用方法 `loa
2727
- exclude 排除部分字段
2828
- strict 参数无效时,是否报错
2929
- error_messages 自定义错误信息
30-
- many 转化为 list
30+
- many 可以将转化为在 nested 中传入 object list
31+
- `load_only` 或者 `dump_only` 都是字面意思
3132
- attribute 别名,这个就很神奇。在 `load` 中表示 `load_to`, 在 `dump` 中表示 `dump_from`
32-
- 在 python3 中 ,marshmallow 统一去除了 `load_from``dump_to` 字段,用 `data_key` 来表述
33-
- load_only 或者 `dump_only` 字面意思
33+
- 在 python3 中,marshmallow 统一去除了 `load_from``dump_to` 字段,用 `data_key` 来表述
34+
- 在 python3 中,missing 和 default 的作用时间发生了改变,传入`missing={}` load 的结果就是`{}` 而不是会继续 deserialize
3435

3536
除了基本数据类型,如 Str, Int, Float, Dict, List 等,还有组合结构类型 Nested 和函数转化 Function 等。
3637

content/pickle.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,5 @@ My name is Mary and I'm 21 years old
8686
pickle 与 json 的区别,json 的 dumps 和 loads 的返回都是字典,而 pickle 可以是对象,将对象 dumps 然后 loads 出来。
8787

8888
pickle 返回的对象是 完全的重现传入的对象,不仅仅是构造参数,类属性和实例属性。还有私有变量和挂载的的变量方法。
89+
90+
所以在缓存装饰器中,一般使用 pickle 做数据对象的序列化和反序列化,来实现数据的装载和卸载。

content/py-spy.md

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
## py-spy
2+
3+
python 性能分析工具,可以用来生成火焰图,查看程序代码性能瓶颈,或者动态查看代码运行时间消耗。
4+
5+
### record
6+
7+
生成火焰图,🔥
8+
9+
```
10+
py-spy record -o profile.svg --pid 12345
11+
# OR
12+
py-spy record -o profile.svg -- python myprogram.py
13+
```
14+
15+
### top
16+
17+
查看程序运行时
18+
19+
```
20+
py-spy top --pid 12345
21+
# OR
22+
py-spy top -- python myprogram.py
23+
```
24+
25+
### dump
26+
27+
查看函数调用堆栈
28+
29+
```
30+
py-spy dump --pid 12345
31+
```
32+
33+
### 火焰图
34+
35+
查看火焰图中占比最大的代码行数进行分析。
36+
37+
[如何读懂火焰图?](http://www.ruanyifeng.com/blog/2017/09/flame-graph.html)
38+
39+
### pyflame
40+
41+
pyflame 工具也可以用来生成火焰图做性能分析,就是用起来比较麻烦。

0 commit comments

Comments
 (0)