Ados

a fullstack game worker

0%

每天进步一点点030 - 最近使用Python的一些笔记

心得

今天看了下 github/awsome-go ,发现以前真的是死心眼,凡事自己死磕,而不是去看看网上成熟的解决方案。
现在有很多 awsome-xxxx 在效率优先的情况下,没必要去死磕,重复造轮子啊。

ImportError: No module named xxxxx

1
2
py_module = __import__(name = module_file_path)
ImportError: No module named xxxxx.xxxxxxx

在需要导入的模组的文件里加入空的 __init__.py 就好了

tornado.queuetornado.queue

tornado.queue为了协程实现了异步生产者/消费者模式,和Python自带的queue为线程而实现的一样。
Queue.get会有一个协程专门等到队列中有数据。如果队列满了,会有专门的协程等待Queue.put争取到空间。
Queue维护了一定数量的未完成的任务,数量从0开始,put会增加数量,task_done会减少数量。

tornado web应用的结构

Tornado web应用是由多个 RequestHandler 子类,一个用于将进来的请求路由到对应的处理的 Application, 一个用来启动的 main() 组成的

setproctitle

修改进程名用的

struct

和lua类似的字节流封装

头字符:表示字节顺序,大小和对齐方式

字符 字节顺序 大小 对齐方式
@ 按原字节 按原字节 按原字节
= 按原字节 标准
< 小端 标准
> 大端 标准
! 网络(=大端) 标准

格式字符

格式 C 类型 Python 类型 标准大小 注释
x 填充字节
c char string of length 1 1
b signed char 整数 1 (3)
B unsigned char 整数 1 (3)
? _Bool bool 1 (1)
h short 整数 2 (3)
H unsigned short 整数 2 (3)
i int 整数 4 (3)
I unsigned int 整数 4 (3)
l long 整数 4 (3)
L unsigned long 整数 4 (3)
q long long 整数 8 (2), (3)
Q unsigned long long 整数 8 (2), (3)
f float 浮点数 4 (4)
d double 浮点数 8 (4)
s char[] string
p char[] string
P void * 整数 (5), (3)
  1. ‘?’ 转换码对应于 C99 定义的 _Bool 类型。 如果此类型不可用,则使用 char 来模拟。 在标准模式下,它总是以一个字节表示。

2.6 新版功能.

  1. ‘q’ 和 ‘Q’ 只有在本地C编译器指出C long long类型行,或者在Windows上支持 __int64的时候才有效。在标准模式下一般都能用。

2.2 新版功能.

  1. 在使用任何整形转码的来包装非整形的时候,如果这个非整形有 __index__() 方法,那么在包装之前会调用此方法来转换参数。 如果没有 __index__()方法,或者调用 __index__() 发生了 TypeError 错误, 那么就会尝试 __int__()。虽然 __int__() 已经废弃,且会抛出 DeprecationWarning

在 2.7 版更改: 2.7中非整数据的 __index__() 全新使用方法。

在 2.7 版更改: 在 2.7 版本中, 并不是所有的整形转换都使用 __int__() 方法, DeprecationWarning 只会在 float 转换的时候抛出。

  1. 对于 ‘f’ 和 ‘d’ 格式字符, 封包形式用的是 IEEE 754 binary32 ('f') 或者 binary64 ('d') 格式, 与平台使用的浮点格式无关。
  1. ‘P’ 格式字符仅对本机字节顺序可用(选择为默认或使用 ‘@’ 字节顺序字符)。 字节顺序字符 ‘=’ 选择使用基于主机系统的小端或大端排序。 struct 模块不会将其解读为本机排序,因此 ‘P’ 格式将不可用。

格式字符之前可以带有整数重复计数。 例如,格式字符串 ‘4h’ 的含义与 ‘hhhh’ 完全相同。

格式之间的空白字符会被忽略;但是计数及其格式字符中不可有空白字符。

对于 ‘?’ 格式字符,返回值为 True 或 False。 在打包时将会使用参数对象的逻辑值。 以本机或标准 bool 类型表示的 0 或 1 将被打包,任何非零值在解包时将为 True。

对于 ‘s’ 格式字符, 个数会解释为字符串的尺寸, 不想其他格式字符一样转换为重复次数; 例如, ‘10s’ 表示的是一个简单的 10-字节字符串, 但是 ‘10c’ 指的是 10 字符。如果没有指定个数的话,默认就是1。为了便于封包,字符串会被截断或者用空字节来填充来适配。对于解包,还是会根据指定的字节数完美的解出字符串。作为特里,’0s’ 意味着一个单个的空的字符串(而 ‘0c’ 代表 0 个字符).

对于’p’ 格式字符对一个 “Pascal string” 编码, 意味着一个短的可变长度的字符串存储在一段指定长度的字节中。第一个字节存储的是字符串的长度,或者是255,无论如何都比255小。接下来的字节都是字符串的字节了。如果传入 pack() 的字符串太长 (比count - 1还要长), 那么只会存储字符串前面的 count-1 字节。如果字符串比 count-1 , 那么会用空字节来填充,这样一来就可以用精确的字节数。注意,对于 unpack(), ‘p’ 格式字符需要消费 count 字节,但是字符串永远都不要超过255个字符。

对于 ‘P’ 格式字符,返回值是一个 Python 整形或者长整形,这取决于在转换为整形之后返回的指针的需要的大小。 NULL 指针永远是返回 Python 整数 0。在封包指针大小的值的时候, 会用到 Python 整形或者长整形。例如: Alpha 和 Merced 处理器使用的是 64-bit 指针值,意味着会用一个 Python 长整型来持有这个指针; 其他平台使用的是 32-bit 指针,那么他会用 Python 整形。

Python 2.7 struct

Tornado

WebSocket的使用方式

1
2
3
4
5
6
7
8
9
10
11
12
import tornado
import tornado.httpserver
import tornado.ioloop

app = tornado.web.Application([
(r"/", tornado.websocket.WebSocketHandlerExtended),
])

self._http_server = tornado.httpserver.HTTPServer(app)
self._http_server.bind(port) # websocket 端口
self._http_server.start(num_processes) #num_processes子进程数
tornado.ioloop.IOLoop.instance().start()

greenlet

轻量级协程,gevent 也是用的 greenlet

  1. 经常与线程 threads,或者Python内置的携程async def配合使用
  2. 多线程有并发性的问题,需要用 queue 或者 locks 来避免 race condition,deadlock 以及其他的问题。greenlet之间是有序协作的,同时只能有一个greenlet运行。可以完全控制greenlet的切换,从而解决了竞态条件问题。
  3. 线程需要申请系统资源,如线程栈,系统预留,而 greenlet 只需要很少的资源

greenlet().switch()切换到这个调用 switch 的协程

greenlet

Python 编码出错的问题

文件头里有

1
2
#!/usr/bin/env python
# -*- coding: utf-8 -*-

VS Code工具栏也显示的 UTF-8,那么看看控制台是否有乱码,有的话运行:chcp 65001 试试看

之前面试被问到过的MySQL引擎问题

MySQL引擎介绍

collections库

1
2
3
4
5
6
7
8
9
10
11
# Counter
c = collections.Counter("hello world, hello world,hello world,hello ")
print c
# 查看元素
print list(c.elements())
# 获取元素的个数,也可以用get()
print c["h"]
c = collections.Counter("hello world hello world hello ".split())
print c
# c.update()
# defaultdict:指定value类型,不存在的给初始值

Counter({‘l’: 11, ‘o’: 7, ‘ ‘: 5, ‘e’: 4, ‘h’: 4, ‘d’: 3, ‘,’: 3, ‘r’: 3, ‘w’: 3})

[‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘ ‘, ‘e’, ‘e’, ‘e’, ‘e’, ‘d’, ‘d’, ‘d’, ‘h’, ‘h’, ‘h’, ‘h’, ‘l’, ‘l’, ‘l’, ‘l’, ‘l’, ‘l’, ‘l’, ‘l’, ‘l’, ‘l’, ‘l’, ‘o’, ‘o’, ‘o’, ‘o’, ‘o’, ‘o’, ‘o’, ‘,’, ‘,’, ‘,’, ‘r’, ‘r’, ‘r’, ‘w’, ‘w’, ‘w’]

4

Counter({‘hello’: 3, ‘world’: 2})

1
2
3
4
5
6
7
8
d = collections.defaultdict(int)
d["a"] += 2
print d
s = [("a","b"),("b","c"),("a","c"),("a","d")]
d = collections.defaultdict(list)
for k,v in s:
d[k].append(v)
print d

defaultdict(<type ‘int’>, {‘a’: 2})

defaultdict(<type ‘list’>, {‘a’: [‘b’, ‘c’, ‘d’], ‘b’: [‘c’]})

1
2
3
4
5
6
7
8
9
# OrderedDict:保留添加顺序
o = collections.OrderedDict()
o["1"] = 1
o["3"] = 3
o['2']=2
o["10"]=10
o["8"]=8
o["1"]=100 #重复赋值不会重新排序
print o

OrderedDict([(‘1’, 100), (‘3’, 3), (‘2’, 2), (‘10’, 10), (‘8’, 8)])

1
2
3
4
5
6
7
8
9
# namedtuple(命名元组的构造器)
# 3种命名元组的方法
p = collections.namedtuple("Person",["age","height","name"])
print p
h = collections.namedtuple("Human","age, height, name")
Human1 = collections.namedtuple("Human1", "age height name")
tom = p(30, 178, "Tom")
print tom
print tom.age

<class ‘main.Person’>

Person(age=30, height=178, name=’Tom’)

30

1
2
3
4
5
6
7
8
9
10
11
# deque 返回一个新的双向队列对象,支持线程安全,对于两端添加或者弹出,时间复杂度O(1)
# 虽然list对象也支持类似操作,但是这里优化了定长操作(pop(0)、insert(0,v))的开销
# 没指定maxLen,可以增长到任意长度,定长的如果满了会从另一端弹出
dq = collections.deque(maxlen=6)
print dq
dq.extend('python') # 从队列右侧添加iterable中的元素
print dq
dq.append("he") # 添加到右侧
print dq
dq.appendleft("ma") # 添加做左侧
print dq

deque([], maxlen=6)

deque([‘p’, ‘y’, ‘t’, ‘h’, ‘o’, ‘n’], maxlen=6)

deque([‘y’, ‘t’, ‘h’, ‘o’, ‘n’, ‘he’], maxlen=6)

deque([‘ma’, ‘y’, ‘t’, ‘h’, ‘o’, ‘n’], maxlen=6)

装饰器

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#!/usr/bin/env python
# -*- coding: utf-8 -*-

def a_new_decorator(a_func):
from functools import wraps
# 不加合格的话在外头打印func.__name__会打印到这里来
@wraps(a_func)
def warp_the_func():
print "Wrap Layer1 begin"
a_func()
print "Wrap Layer end"

return warp_the_func

def func_need_decotator():
print "Func Main"

func_need_decotator()
print "-----------------------------"
func_decotated = a_new_decorator(func_need_decotator)
func_decotated()

print "-----------------------------"

@a_new_decorator
def fun_with_decorator():
print "Hehe"

fun_with_decorator()

Func Main

Wrap Layer1 begin
Func Main
Wrap Layer end


Wrap Layer1 begin
Hehe
Wrap Layer end

Java注解

标记注解

1
2
3
4
//有点像定义一个接口一样,只不过它多了一个@
public @interface MyAnnotation {

}

元数据注解

普通使用

定义
1
2
3
4
5
public @interface MyAnnotation {
//定义了两个成员变量
String username();
int age();
}
使用
1
2
3
4
5
6

//注解拥有什么属性,在修饰的时候就要给出相对应的值
@MyAnnotation(username = "zhongfucheng", age = 20)
public void add(String username, int age) {

}

默认值

定义
1
2
3
4
5
public @interface MyAnnotation {
//定义了两个成员变量
String username() default "zicheng";
int age() default 23;
}
使用
1
2
3
@MyAnnotation()
public void add(String username, int age) {
}

注解为Value

定义
1
2
3
public @interface MyAnnotation2 {
String value();
}
使用
1
2
3
@MyAnnotation2("zhongfucheng")
public void find(String id) {
}