啊
10,IO
输入输出
同步异步
1)文件读写
①读
try或with打开文件;
read或readline读取文件;
有read()方法的对象,叫做file-like Object.类文件对象。
- senrsl@senrsl-T540p:~/test/python3$ touch tmp
- senrsl@senrsl-T540p:~/test/python3$ echo -e "1\n啊\n3\n\t4\n5">>tmp
- senrsl@senrsl-T540p:~/test/python3$ python3
- Python 3.4.3 (default, Oct 14 2015, 20:28:29)
- [GCC 4.8.4] on linux
- Type "help", "copyright", "credits" or "license" for more information.
- >>> def readFileTry():
- ... try:
- ... f = open("tmp","r");
- ... print(f.read());
- ... finally:
- ... if f:
- ... f.close();
- ...
- >>> readFileTry();
- 1
- 啊
- 3
- 4
- 5
- >>> def readFileWith():
- ... with open("tmp","r") as f:
- ... print(f.read());
- ...
- >>> readFileWith();
- 1
- 啊
- 3
- 4
- 5
- >>>
- >>> def readFileWithASize():
- ... with open("tmp","r") as f:
- ... for size in f.read(4):
- ... print(size);
- ...
- >>> readFileWithASize();
- 1
- 啊
- >>> def readFileWithASize():
- ... with open("tmp","r") as f:
- ... print(f.read(10));
- ...
- >>> readFileWithASize();
- 1
- 啊
- 3
- 4
- 5
- >>> def readFileWithASize():
- ... with open("tmp","r") as f:
- ... print(f.read(3));
- ...
- >>> readFileWithASize();
- 1
- 啊
- >>> def readFileWithLine():
- ... with open("tmp","r") as f:
- ... for line in f.readlines():
- ... print(line.strip());
- ...
- >>> readFileWithLine();
- 1
- 啊
- 3
- 4
- 5
- >>>
语法:
f = open("tmp","r",encoding="gbk",errors="ignore");打开模式:r为只读,w为覆盖写,a为追加写,b为二进制
指向变量 = open("目标文件","打开模式",encoding="打开编码",errors="出现错误怎么办");
②写
- >>> def writeFileTry():
- ... f = open("tmp","w");
- ... f.write("fuck");
- ... f.close();
- ...
- >>> writeFileTry();
- >>> readFileTry();
- fuck
- >>> def writeFileWith():
- ... with open("tmp","w") as f:
- ... f.write("fuck2");
- ...
- >>> writeFileWith();
- >>> readFileWith();
- fuck2
- >>> def writeFileWith():
- ... with open("tmp","a") as f:
- ... f.write("fuck22222222");
- ...
- >>> readFileWith();
- fuck2
- >>> writeFileWith();
- >>> readFileWith();
- fuck2fuck22222222
- >>> writeFileWith();
- >>> writeFileWith();
- >>> readFileWith();
- fuck2fuck22222222fuck22222222fuck22222222
- >>>
2)StringIO和BytesIO
封了俩工具出来
①StringIO
这个是内存文本读写
- >>> from io import StringIO;
- >>> f = StringIO();
- >>> f.write("你好");
- 2
- >>> f.write("浏阳河啊");
- 4
- >>> print(f.getvalue());
- 你好浏阳河啊
- >>>
- >>> f.write("\n浪页吗浪那个浪");
- 8
- >>> f.write("\n啊");
- 2
- >>> print(f.getvalue());
- 你好浏阳河啊
- 浪页吗浪那个浪
- 啊
- >>> def readStringIO():
- ... f = StringIO("1\n\t222\n33333");
- ... while True:
- ... s = f.readline();
- ... if s == "":
- ... break;
- ... print(s.strip());
- ...
- >>> readStringIO();
- 1
- 222
- 33333
- >>>
这个是类似于Xml流读取,有记忆位置。
②BytesIO
- >>> from io import BytesIO;
- >>> f = BytesIO();
- >>> f.write("啊".encode("utf-8"));
- 3
- >>> print(f.getvalue());
- b'\xe5\x95\x8a'
- >>>
- >>> from io import BytesIO;
- >>> f = BytesIO(b"xe5\x95\x8a");
- >>> f.read();
- b'xe5\x95\x8a'
- >>>
3)文件目录操作
①系统名称和环境变量
- >>> import os;
- >>> os.name;
- 'posix'
- >>> os.uname();
- posix.uname_result(sysname='Linux', nodename='senrsl-T540p', release='3.19.0-28-generic', version='#30~14.04.1-Ubuntu SMP Tue Sep 1 09:32:55 UTC 2015', machine='x86_64')
- >>> os.environ;# 环境变量
- environ({'XMODIFIERS': '@im=fcitx', 'SELINUX_INIT': 'YES', 'LS_COLORS': 'rs=0:di=01;34:ln=01;36:mh=00:pi=40;33:so=01;35:do=01;35:bd=40;33;01:cd=40;33;01:or=40;31;01:su=37;41:sg=30;43:ca=30;41:tw=30;42:ow=34;42:st=37;44:ex=01;32:*.tar=01;31:*.tgz=01;31:*.arj=01;31:*.taz=01;31:*.lzh=01;31:*.lzma=01;31:*.tlz=01;31:*.txz=01;31:*.zip=01;31:*.z=01;31:*.Z=01;31:*.dz=01;31:*.gz=01;31:*.lz=01;31:*.xz=01;31:*.bz2=01;31:*.bz=01;31:*.tbz=01;31:*.tbz2=01;31:*.tz=01;31:*.deb=01;31:*.rpm=01;31:*.jar=01;31:*.war=01;31:*.ear=01;31:*.sar=01;31:*.rar=01;31:*.ace=01;31:*.zoo=01;31:*.cpio=01;31:*.7z=01;31:*.rz=01;31:*.jpg=01;35:*.jpeg=01;35:*.gif=01;35:*.bmp=01;35:*.pbm=01;35:*.pgm=01;35:*.ppm=01;35:*.tga=01;35:*.xbm=01;35:*.xpm=01;35:*.tif=01;35:*.tiff=01;35:*.png=01;35:*.svg=01;35:*.svgz=01;35:*.mng=01;35:*.pcx=01;35:*.mov=01;35:*.mpg=01;35:*.mpeg=01;35:*.m2v=01;35:*.mkv=01;35:*.webm=01;35:*.ogm=01;35:*.mp4=01;35:*.m4v=01;35:*.mp4v=01;35:*.vob=01;35:*.qt=01;35:*.nuv=01;35:*.wmv=01;35:*.asf=01;35:*.rm=01;35:*.rmvb=01;35:*.flc=01;35:*.avi=01;35:*.fli=01;35:*.flv=0 1;35:*.gl=01;35:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:', 'XDG_VTNR': '7', 'GNOME_KEYRING_PID': '2156', 'WINDOWID': '33554677', 'LANGUAGE': 'zh_CN:zh', 'COLORTERM': 'gnome-terminal', 'DEFAULTS_PATH': '/usr/share/gconf/ubuntu.default.path', 'IM_CONFIG_PHASE': '1', 'GDM_LANG': 'zh_CN', 'VTE_VERSION': '3409', '_': '/usr/bin/python3', 'GDMSESSION': 'ubuntu', 'LOGNAME': 'senrsl', 'USER': 'senrsl', 'SSH_AUTH_SOCK': '/run/user/1000/keyring-MZ4zFJ/ssh', 'TEXTDOMAIN': 'im-config', 'UPSTART_INSTANCE': '', 'QT_QPA_PLATFORMTHEME': 'appmenu-qt5', 'DESKTOP_SESSION': 'ubuntu', 'HOME': '/home/senrsl', 'GPG_AGENT_INFO': '/run/user/1000/keyring-MZ4zFJ/gpg:0:1', 'PATH': '/home/senrsl/tools/gerrit/buck/bin:/home/senrsl/android/source/bin:/home/senrsl/android/android-ndk-r10e:/home/senrsl/android/android-sdk-linux/tools:/home/senrsl/android/android-sdk-linux/platform-tools:/home/senrsl/java/jdk1.7.0_71/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games', 'DISPLAY': ':0', 'SHELL': '/bin/bash', 'JOB': 'gnome-session', 'TEXTDOMAINDIR': '/usr/share/locale/', 'TERM': 'xterm', 'UPSTART_EVENTS': 'started starting', 'XDG_RUNTIME_DIR': '/run/user/1000', 'XDG_CONFIG_DIRS': '/etc/xdg/xdg-ubuntu:/usr/share/upstart/xdg:/etc/xdg', 'XDG_SESSION_ID': 'c2', 'GTK_IM_MODULE': 'fcitx', 'LESSCLOSE': '/usr/bin/lesspipe %s %s', 'GNOME_KEYRING_CONTROL': '/run/user/1000/keyring-MZ4zFJ', 'QT4_IM_MODULE': 'fcitx', 'JAVA_HOME': '/home/senrsl/java/jdk1.7.0_71', 'XDG_GREETER_DATA_DIR': '/var/lib/lightdm-data/senrsl', 'XAUTHORITY': '/home/senrsl/.Xauthority', 'XDG_SEAT_PATH': '/org/freedesktop/DisplayManager/Seat0', 'QT_IM_MODULE': 'xim', 'LESSOPEN': '| /usr/bin/lesspipe %s', 'JRE_HOME': '/home/senrsl/java/jdk1.7.0_71/jre', 'XDG_SESSION_PATH': '/org/freedesktop/DisplayManager/Session0', 'MANDATORY_PATH': '/usr/share/gconf/ubuntu.mandatory.path', 'CLUTTER_IM_MODULE': 'xim', 'NDK_HOME': '/home/senrsl/android/android-ndk-r10e', 'LANG': 'zh_CN.UTF-8', 'XDG_SEAT': 'seat0', 'PWD': '/home/senrsl/test/python3', 'GNOME_DESKTOP_SESSION_ID': 'this-is-deprecated', 'XDG_CURRENT_DESKTOP': 'Unity', 'COMPIZ_CONFIG_PROFILE': 'ubuntu', 'DBUS_SESSION_BUS_ADDRESS': 'unix:abstract=/tmp/dbus-aZpxlumDfe', 'XDG_DATA_DIRS': '/usr/share/ubuntu:/usr/share/gnome:/usr/local/share/:/usr/share/', 'ANDROID_NDK_ROOT': '/home/senrsl/android/android-ndk-r10e', 'COMP_WORDBREAKS': ' \t\n"\'><;|&(:', 'SHLVL': '1', 'INSTANCE': 'Unity', 'GTK_MODULES': 'overlay-scrollbar:unity-gtk-module', 'SESSIONTYPE': 'gnome-session', 'UPSTART_JOB': 'unity-settings-daemon', 'UPSTART_SESSION': 'unix:abstract=/com/ubuntu/upstart-session/1000/2158', 'ANDROID_HOME': '/home/senrsl/android/android-sdk-linux', 'CLASSPATH': '.:/home/senrsl/java/jdk1.7.0_71/lib:/home/senrsl/java/jdk1.7.0_71/jre/lib', 'OLDPWD': '/home/senrsl/test/python3/unittest'})
- >>> os.environ.get("PATH");
- '/home/senrsl/tools/gerrit/buck/bin:/home/senrsl/android/source/bin:/home/senrsl/android/android-ndk-r10e:/home/senrsl/android/android-sdk-linux/tools:/home/senrsl/android/android-sdk-linux/platform-tools:/home/senrsl/java/jdk1.7.0_71/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games'
- >>> os.environ.get("x","default");
- 'default'
- >>>
②文件和目录操作
- >>> os.path.abspath(".");
- '/home/senrsl/test/python3'
- >>> os.path.join("/home/senrsl/test/python3","newDir");
- '/home/senrsl/test/python3/newDir'
- >>> os.mkdir("/home/senrsl/test/python3/newDir");
- >>> os.rmdir("/home/senrsl/test/python3/newDir");
- ('/home/senrsl/test/python3', 'newDir')
- >>> os.path.splitext("/home/senrsl/test/python3/newDir/xxx.txt");
- ('/home/senrsl/test/python3/newDir/xxx', '.txt')
- >>> os.rename("tmp","tmp01");
- >>> os.remove("tmp01");
- >>> [x for x in os.listdir(".")if os.path.isdir(x)]
- ['__pycache__', 'doctest', 'unittest', 'newTxt01']
- >>> [x for x in os.listdir(".")if os.path.isfile(x) and os.path.splitext(x)[1]==".py"]
- ['helloWorld01.py', 'helloWorld.py']
- >>>
4)序列化
把变量从内存中变成可存储或传输的过程叫序列化。
picking,serialization,marshaling,flattening....
把变量内容从序列化的对象重新读到内存里称之为反序列化,叫unpicking.
①pickle模块用来序列化。
序列化后保存到文件,然后读取后反序列化解析。
- >>> import pickle;
- >>> d = dict(name="aaa",age=10);
- >>> pickle.dumps(d);
- b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\nX\x04\x00\x00\x00nameq\x02X\x03\x00\x00\x00aaaq\x03u.'
- >>> f = open("dump.txt","wb");
- >>> pickle.dump(d,f);
- >>> f.close();
- >>>
- >>> f = open("dump.txt","rb");
- >>> d = pickle.load(f);
- >>> f.close();
- >>> d
- {'age': 10, 'name': 'aaa'}
- >>>
②使用json模块序列化
json和python数据类型对应关系:
- >>> import json;
- >>> d = dict(name="aa",age=10);
- >>> json.dumps(d);
- '{"age": 10, "name": "aa"}'
- >>>
- >>> json_str = json.dumps(d);
- >>> json.loads(json_str);
- {'age': 10, 'name': 'aa'}
- >>>
官方图对应如下:
- JSON类型 Python类型
- {} dict
- [] list
- "string" str
- 1234.56 int或float
- true/false True/False
- null None
☂③类序列化为json
序列化:
反序列化:
- >>> import json;
- >>>
- >>> class Student(object):
- ... def __init__(self,name,age):
- ... self.name = name;
- ... self.age = age;
- ...
- >>> s = Student("bbb",10);
- >>> def student2dict(std):
- ... return{
- ... "name":std.name,
- ... "age":std.age
- ... }
- ...
- >>> print(json.dumps(s,default=student2dict));
- {"name": "bbb", "age": 10}
- >>>
- >>> print(json,dumps(s,default=lambda obj:obj.__dict__));
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- NameError: name 'dumps' is not defined
- >>>
- >>> def dict2student(d):
- ... return Student(d["name"],d["age"]);
- ...
- >>> json_str = '{"name":"cccc","age":10}';
- >>> print(json.loads(json_str,object_hook=dict2student));
- <__main__.Student object at 0x7f3d23e94ac8>
- >>>
11,进程和线程
1)多进程
①创建一个子进程
使用fork()创建子进程
这种方法不适用win系统
fork()函数调用一次返回两次。调用时,操作系统自动把当前进程(父进程)复制一份(子进程),然后分别在这俩进程里返回。
- senrsl@senrsl-T540p:~/test/python3$ mkdir process
- senrsl@senrsl-T540p:~/test/python3$ touch process/test_fock.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_fock.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_fock.py
- Process 27345 start....
- 父线程27345将创建一个子线程27346
- 子线程是27346 and 父线程是27345
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_fock.py
- import os;
- print("Process %s start...." % os.getpid());
- pid = os.fork();
- if pid == 0:
- print("子线程是%s and 父线程是%s" % (os.getpid(),os.getppid()));
- else:
- print("父线程%s将创建一个子线程%s" % (os.getpid(),pid));
- senrsl@senrsl-T540p:~/test/python3$
②使用multiprocessing模块创建子进程
千万不要让文件名跟系统内置的重复,之前起名叫multiprocessing.py,一直ImportError: cannot import name 'Process',然后改名并把之前那个删了就好了。。。。
- senrsl@senrsl-T540p:~/test/python3$ touch process/test_multiprocessing.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_multiprocessing.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_multiprocessing.py
- 父线程4096
- 子线程启动
- 运行子线程test 标号为4097
- 子线程结束
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_multiprocessing.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from multiprocessing import Process;
- import os;
- def run_proc(name):
- print("运行子线程%s 标号为%s" % (name,os.getpid()));
- if __name__ == "__main__":
- print("父线程%s" % os.getpid());
- p = Process(target=run_proc,args=("test",));
- print("子线程启动");
- p.start();
- p.join();
- print("子线程结束");
- senrsl@senrsl-T540p:~/test/python3$
③进程池pool
Pool的默认大小是CPU核数,上面设置的8,意为最多同时可以跑8个进程。
- senrsl@senrsl-T540p:~/test/python3$ touch process/test_pool.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_pool.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_pool.py
- 父进程8309
- 等待执行完成
- 运行任务0 8310
- 运行任务1 8311
- 运行任务2 8312
- 运行任务3 8313
- 运行任务4 8314
- 运行任务5 8315
- 运行任务6 8316
- 运行任务7 8317
- 任务2运行0.28秒
- 运行任务8 8312
- 任务5运行0.66秒
- 任务6运行0.90秒
- 任务8运行0.95秒
- 任务3运行1.77秒
- 任务4运行1.89秒
- 任务0运行1.96秒
- 任务1运行2.69秒
- 任务7运行2.79秒
- 执行结束
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_pool.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from multiprocessing import Pool;
- import os,time,random;
- def long_time_task(name):
- print("运行任务%s %s" % (name,os.getpid()));
- start = time.time();
- time.sleep(random.random() * 3);
- end = time.time();
- print("任务%s运行%0.2f秒" % (name,(end-start)));
- if __name__ == "__main__":
- print("父进程%s" % os.getpid());
- p = Pool(8);
- for i in range(9):
- p.apply_async(long_time_task,args=(i,));
- print("等待执行完成");
- p.close();
- p.join();
- print("执行结束");
- senrsl@senrsl-T540p:~/test/python3$
④子进程
subprocess模块的用法
手动输入:
- >>> import subprocess;
- >>> print("$ nslookup www.python.org");
- $ nslookup www.python.org
- >>> r = subprocess.call(["nslookup","www.python.org"]);
- Server: 127.0.1.1
- Address: 127.0.1.1#53
- Non-authoritative answer:
- www.python.org canonical name = python.map.fastly.net.
- python.map.fastly.net canonical name = prod.python.map.fastlylb.net.
- Name: prod.python.map.fastlylb.net
- Address: 151.101.88.223
- >>> print("exit",r);
- exit 0
- >>>
- senrsl@senrsl-T540p:~/test/python3$ touch process/test_subprocess.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_subprocess.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_subprocess.py
- $ nslookup
- Server: 127.0.1.1
- Address: 127.0.1.1#53
- Non-authoritative answer:
- python.org mail exchanger = 50 mail.python.org.
- Authoritative answers can be found from:
- Exit code: 0
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_subprocess.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import subprocess;
- print("$ nslookup");
- p = subprocess.Popen(["nslookup"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE);
- output,err = p.communicate(b"set q=mx\npython.org\nexit\n");
- print(output.decode("utf-8"));
- print("Exit code:",p.returncode);
- senrsl@senrsl-T540p:~/test/python3$
⑤进程间通信
以Queue为例,实现一个读一个写:
进程间通信可以使用Queue,Pipes等实现。
- senrsl@senrsl-T540p:~/test/python3$ touch process/test_queue.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_queue.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_queue.py
- 写进程:16811
- put a to queue....
- 读进程:16812
- get a from queue....
- put b to queue....
- get b from queue....
- put C to queue....
- get C from queue....
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_queue.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from multiprocessing import Process,Queue;
- import os,time,random;
- def write(q):
- print("写进程:%s" % os.getpid());
- for value in ["a","b","C"]:
- print("put %s to queue...." % value);
- q.put(value);
- time.sleep(random.random());
- def read(q):
- print("读进程:%s" % os.getpid());
- while True:
- value = q.get(True);
- print("get %s from queue...." % value);
- if __name__ == "__main__":
- q = Queue();
- pw = Process(target=write,args=(q,));
- pr = Process(target=read,args=(q,));
- pw.start();
- pr.start();
- pw.join();
- pr.terminate();
- senrsl@senrsl-T540p:~/test/python3$
2)多线程
多任务可以由多进程完成,也可以由一个进程内多线程完成。
python标准库提供两个模块,_thread和threading,后者对前者进行了封装。
①使用threading启动线程
- senrsl@senrsl-T540p:~/test/python3$ touch process/test_threading.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_threading.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_threading.py
- 线程MainThread运行中。。。
- 线程LoopThread运行中。。。。
- 线程LoopThread >>>>>> 1
- 线程LoopThread >>>>>> 2
- 线程LoopThread >>>>>> 3
- 线程LoopThread >>>>>> 4
- 线程LoopThread >>>>>> 5
- 线程LoopThread结束
- 线程MainThread结束
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_threading.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import time,threading;
- def loop():
- print("线程%s运行中。。。。" % threading.current_thread().name);
- n = 0;
- while n <5:
- n = n+ 1;
- print("线程%s >>>>>> %s" % (threading.current_thread().name,n));
- time.sleep(1);
- print("线程%s结束" % threading.current_thread().name);
- print("线程%s运行中。。。" % threading.current_thread().name);
- t = threading.Thread(target=loop,name="LoopThread");
- t.start();
- t.join();
- print("线程%s结束" % threading.current_thread().name);
- senrsl@senrsl-T540p:~/test/python3$
②线程锁
不加锁,变量结果随机化:
加锁:
- senrsl@senrsl-T540p:~/test/python3$ touch process/test_lock.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_lock.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
- 执行完成,余额: 5
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
- 执行完成,余额: -16
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_lock.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import time,threading;
- balance = 0;
- def change_it(n):
- global balance;
- balance = balance +n;
- balance = balance -n;
- def run_thread(n):
- for i in range(1000000):
- change_it(n);
- t1 = threading.Thread(target=run_thread,args=(5,));
- t2 = threading.Thread(target=run_thread,args=(8,));
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- print("执行完成,余额:",balance);
- senrsl@senrsl-T540p:~/test/python3$
加锁后,执行速度明显变慢了。
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_lock.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
- 执行完成,余额: 0
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
- 执行完成,余额: 0
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
- 执行完成,余额: 0
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_lock.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import time,threading;
- balance = 0;
- lock = threading.Lock();
- def change_it(n):
- global balance;
- balance = balance +n;
- balance = balance -n;
- def run_thread(n):
- for i in range(1000000):
- lock.acquire(); # 持有锁:
- try:
- change_it(n);
- finally:
- lock.release();#释放锁
- t1 = threading.Thread(target=run_thread,args=(5,));
- t2 = threading.Thread(target=run_thread,args=(8,));
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- print("执行完成,余额:",balance);
- senrsl@senrsl-T540p:~/test/python3$
③GIL锁
历史遗留,GIL锁,Global Interpreter Lock,任何python线程执行前,必须先获取GIL锁,每执行100条字节自动释放。
所以,多线程并非多核任务,要实现多核任务可以用多进程实现,每个进程都有自己独立的GIL锁。
3)ThreadLocal
ThreadLocal解决参数在一个线程中各个函数之间互相传递的问题
全局定义,线程独立。
- senrsl@senrsl-T540p:~/test/python3$ touch process/test_thread_local.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/test_thread_local.py
- senrsl@senrsl-T540p:~/test/python3$ python3 process/test_thread_local.py
- 你好,i小A 线程Thread-0001
- 你好,小B 线程Thread-B
- senrsl@senrsl-T540p:~/test/python3$ cat process/test_thread_local.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import threading;
- local_school = threading.local();
- def process_student():
- std = local_school.student;
- print("你好,%s 线程%s" % (std,threading.current_thread().name));
- def process_thread(name):
- local_school.student = name;
- process_student();
- t1 = threading.Thread(target=process_thread,args = ("i小A",),name="Thread-0001");
- t2 = threading.Thread(target=process_thread,args=("小B",),name="Thread-B");
- t1.start();
- t2.start();
- t1.join();
- t2.join();
- senrsl@senrsl-T540p:~/test/python3$
4)分布式进程
Process比Thread稳定
然后开两个终端,分别启动这俩
- senrsl@senrsl-T540p:~/test/python3$ touch process/process_server.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/process_server.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/process_worker.py
- senrsl@senrsl-T540p:~/test/python3$ vi process/process_worker.py
master端:
worker端:
- senrsl@senrsl-T540p:~$ cd test/python3/
- senrsl@senrsl-T540p:~/test/python3$ python3 process/process_server.py
- 添加任务6055....
- 添加任务6920....
- 添加任务9338....
- 添加任务9157....
- 添加任务5901....
- 添加任务2697....
- 添加任务6492....
- 添加任务889....
- 添加任务8875....
- 添加任务4819....
- 获取数据:
- 返回6055 * 6055 = 36663025!
- 返回6920 * 6920 = 47886400!
- 返回9338 * 9338 = 87198244!
- 返回9157 * 9157 = 83850649!
- 返回5901 * 5901 = 34821801!
- 返回2697 * 2697 = 7273809!
- 返回6492 * 6492 = 42146064!
- 返回889 * 889 = 790321!
- 返回8875 * 8875 = 78765625!
- 返回4819 * 4819 = 23222761!
- 退出
- senrsl@senrsl-T540p:~/test/python3$
图示:
- senrsl@senrsl-T540p:~/test/python3$ python3 process/process_server.py
- 添加任务6055....
- 添加任务6920....
- 添加任务9338....
- 添加任务9157....
- 添加任务5901....
- 添加任务2697....
- 添加任务6492....
- 添加任务889....
- 添加任务8875....
- 添加任务4819....
- 获取数据:
- 返回6055 * 6055 = 36663025!
- 返回6920 * 6920 = 47886400!
- 返回9338 * 9338 = 87198244!
- 返回9157 * 9157 = 83850649!
- 返回5901 * 5901 = 34821801!
- 返回2697 * 2697 = 7273809!
- 返回6492 * 6492 = 42146064!
- 返回889 * 889 = 790321!
- 返回8875 * 8875 = 78765625!
- 返回4819 * 4819 = 23222761!
- 退出
- senrsl@senrsl-T540p:~/test/python3$
源码:
master端等待异常的时候没有去关闭,所以下次再启动会端口占用。所以加try-catch很重要。
- senrsl@senrsl-T540p:~/test/python3$ cat process/process_server.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import random,time,queue;
- from multiprocessing.managers import BaseManager
- #发送任务的队列
- task_queue = queue.Queue();
- #接收任务队列
- result_queue = queue.Queue();
- class QueueManager (BaseManager):
- pass;
- #把两个Queue都注册到网络上,callable参数关联了Queue对象
- QueueManager.register("get_task_queue",callable=lambda:task_queue);
- QueueManager.register("get_result_queue",callable=lambda:result_queue);
- #绑定端口5000,设置验证码abc
- manager = QueueManager(address=("",5000),authkey=b"abc");
- #启动Queue
- manager.start();
- #获得通过网络访问的Queue对象
- task = manager.get_task_queue();
- result = manager.get_result_queue();
- #添加任务
- for i in range(10):
- n = random.randint(0,10000);
- print("添加任务%d...." % n);
- task.put(n);
- #从result队列读取结果
- print("获取数据:");
- for i in range(10):
- r = result.get(timeout=10);
- print("返回%s" % r);
- #关闭
- manager.shutdown();
- print("退出");
- senrsl@senrsl-T540p:~/test/python3$ cat process/process_worker.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import time,sys,queue;
- from multiprocessing.managers import BaseManager;
- class QueueManager(BaseManager):
- pass;
- QueueManager.register("get_task_queue");
- QueueManager.register("get_result_queue");
- server_addr = "127.0.0.1";
- print("连接到服务%s。。。。" % server_addr);
- m = QueueManager(address=(server_addr,5000),authkey=b"abc");
- m.connect();
- task = m.get_task_queue();
- result = m.get_result_queue();
- for i in range(10):
- try:
- n = task.get(timeout=1);
- print("运行任务%d * %d...." % (n,n));
- r = "%d * %d = %d!" % (n,n,n*n);
- time.sleep(1);
- result.put(r);
- except Queue.Empty:
- print("空异常");
- print("workder exit!");
- senrsl@senrsl-T540p:~/test/python3$
12,正则表达式
正则,又见正则
基本使用方法:
- >>> import re;
- >>> re.split(r"[\s\,]","a,b,c d");
- ['a', 'b', 'c', 'd']
- >>> re.split(r"\s\,\;+","a,b;;c d");
- ['a,b;;c d']
- >>> re.split(r"[\s\,\;]+","a,b;;c d");
- ['a', 'b', 'c', 'd']
- >>>
一次编译,多次使用:
此处入库
- >>> import re;
- >>> re_telphone = re.compile(r"^(\d{3})-(\d{3,8})$");#编译
- >>> re_telphone.match("010-12345").groups();#使用
- ('010', '12345')
- >>> re_telphone.match("010-10086").groups();
- ('010', '10086')
- >>>
13,常用内建模块
batteries included
1)datetime
处理日期和时间
- senrsl@senrsl-T540p:~/test/python3$ vi module/test_datetime.py
- senrsl@senrsl-T540p:~/test/python3$ python3 module/test_datetime.py
- 2016-07-01 15:20:45.316538
- <class 'datetime.datetime'>
- datetime为2016-07-01 11:12:00
- timestamp为:1467342720.0
- 转换timestamp为datetime,使用本地时区:2016-07-01 11:12:00
- 转换timestamp为datetime,使用utc标准时区:2016-07-01 03:12:00
- str转换为datetime: 2016-07-01 11:26:11
- datetime转换为str: Fri,Jul 01 15:20
- 2016-07-01 15:20:45.316538
- 2016-07-02 01:20:45.316538
- 2016-06-30 15:20:45.316538
- 2016-07-04 03:20:45.316538
- UTC时间: 2016-07-01 07:20:45.324733+00:00
- 北京时间: 2016-07-01 15:20:45.324733+08:00
- 东京时间 2016-07-01 16:20:45.324733+09:00
- 北京时间转东京时间 2016-07-01 16:20:45.324733+09:00
- 强制设置+8时区 2016-07-01 15:20:45.316538+08:00
- senrsl@senrsl-T540p:~/test/python3$ cat module/test_datetime.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from datetime import datetime,timedelta,timezone;
- #获取当前日期和时间
- now = datetime.now();
- print(now);
- print(type(now));
- #获取指定日期和时间
- dt = datetime(2016,7,1,11,12);
- print("datetime为%s" % dt);
- #转换为timestamp
- #python小数位表示毫秒,算法为java/1000=python
- t = dt.timestamp();
- print("timestamp为:%s" % t);
- #timestamp转换为datetime
- print("转换timestamp为datetime,使用本地时区:%s" % datetime.fromtimestamp(t));
- print("转换timestamp为datetime,使用utc标准时区:%s" % datetime.utcfromtimestamp(t));
- #str转换为datetime
- cday = datetime.strptime("2016-7-1 11:26:11","%Y-%m-%d %H:%M:%S");
- print("str转换为datetime:",cday);
- #datetime转换为str
- print("datetime转换为str:",now.strftime("%a,%b %d %H:%M"));
- #datetime加减
- print(now);
- print(now + timedelta(hours = 10));
- print(now - timedelta(days=1));
- print(now + timedelta(days=2,hours=12));
- #拿到UTC时间,转换时区
- utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc);
- print("UTC时间:",utc_dt);
- bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)));
- print("北京时间:",bj_dt);
- tokyo_dt = utc_dt.astimezone(timezone(timedelta(hours=9)));
- print("东京时间",tokyo_dt);
- #北京时间转东京时间
- tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9)));
- print("北京时间转东京时间",tokyo_dt2);
- #默认datetime时区属性为None,强制设置时区属性
- tz_utc_8 = timezone(timedelta(hours=8));#创建+8时区
- set8_dt = now.replace(tzinfo=tz_utc_8);
- print("强制设置+8时区",set8_dt);
- senrsl@senrsl-T540p:~/test/python3$
2)collections
提供集合类
①namedtuple
带名的tuple
- >>> from collections import namedtuple;
- >>> Point = namedtuple("Point",["x","y"]);
- >>> p = Point(1,2);
- >>> p.x
- 1
- >>> p.y
- 2
- >>> isinstance(p,Point);
- True
- >>> isinstance(p,tuple);
- True
- >>>
②deque
两头操作的list
- >>> from collections import deque;
- >>> q = deque(["a","b","c"]);
- >>> q.append("d");
- >>> q.appendleft("e");
- >>> q
- deque(['e', 'a', 'b', 'c', 'd'])
- >>> q.popleft();
- 'e'
- >>> q
- deque(['a', 'b', 'c', 'd'])
- >>>
③defaultdict
当dict的key不存在时返回默认值
④OrderedDict
- >>> from collections import defaultdict;
- >>> dd = defaultdict(lambda:"N/A");
- >>> dd["key1"] = "abc";
- >>> dd["key1"]
- 'abc'
- >>> dd["key2"]
- 'N/A'
- >>>
有序的dict
- >>> from collections import OrderedDict;
- >>> d = dict([("a",1),("b",2),("c",3)]);
- >>> d
- {'c': 3, 'b': 2, 'a': 1}
- >>> od = OrderedDict([("a",1),("b",2),("c",3)]);
- >>> od
- OrderedDict([('a', 1), ('b', 2), ('c', 3)])
- >>>
⑤Counter
一个简单的计数器
- >>> from collections import Counter;
- >>> c = Counter();
- >>> for ch in "fdsafsdafsafsdafjdsalkfsadjffewgfewfa":
- ... c[ch] = c[ch]+1;
- ...
- >>> c
- Counter({'f': 10, 'a': 7, 's': 6, 'd': 5, 'w': 2, 'j': 2, 'e': 2, 'g': 1, 'l': 1, 'k': 1})
- >>>
3)base64
用64个字符表示二进制数据的方法
准备64个字符的数组,然后对二进制每3个字节(Byte)一组,3个字节*8位(bit)=24位.
24位除以4(索引)等于6位一组。
4索引查64字符数组,取值为编码后字符。
如果3字节分组时有余,用\x00补足,再在编码后末尾加相应数的=表示补了多少字节。
因为base64永远是4的倍数,所以传输中可以把后面补的=去掉,接收方收到再补成4的倍数解析。
- >>> import base64;
- >>> base64.b64encode(b'a');
- b'YQ=='
- >>> base64.b64decode(b"b'YQ=='");
- b'm\x84'
- >>> base64.b64decode(b"YQ==");
- b'a'
- >>>
- >>> base64.b64encode(b"i\xb7\x1d\xfb\xef\xff");
- b'abcd++//'
- >>> base64.urlsafe_b64encode(b"i\xb7\x1d\xfb\xef\xff");
- b'abcd--__'
- >>> base64.urlsafe_b64decode(b'abcd--__');
- b'i\xb7\x1d\xfb\xef\xff'
- >>>
4)struct
用于处理bytes和其他二进制数据类型转换
第一个参数是处理指令,>表示字节顺序为big-endian,即网络序,I表示4字节无符号整数,H表示2字节无符号整数。
- >>> import struct;
- >>> struct.pack(">I",10240099);
- b'\x00\x9c@c'
- >>> struct.unpack(">I",b'\x00\x9c@c');
- >>> struct.unpack(">IH",b'\xf0\xf0\xf0\xf0\x80\x80');
- (4042322160, 32896)
- >>>
第二个参数要跟第一个参数指示的长度一致。
处理指令对应表:
地址在https://docs.python.org/3/library/struct.html#format-characters
5)hashlib
提供常见的摘要算法,如MD5,SHA1等
MD5生成固定128位字节,通常用一个32位的16进制字符串表示;
- >>> import hashlib;
- >>> md5 = hashlib.md5();
- >>> md5.update("fuck".encode("utf-8"));
- >>> print(md5.hexdigest());
- 99754106633f94d350db34d548d6091a
- >>> md501 = hashlib.md5();
- >>> md501.update("fu".encode("utf-8"));
- >>> md501.update("ck".encode("utf-8"));
- >>> print(md501.hexdigest());
- 99754106633f94d350db34d548d6091a
- >>>
- >>> sha1 = hashlib.sha1();
- >>> sha1.update("fuck".encode("utf-8"));
- >>> print(sha1.hexdigest());
- 38d0f91a99c57d189416439ce377ccdcd92639d0
- >>>
SHA1生成160位字节,通常用一个40位的16进制字符串表示;
通过原始口令,加一个复杂字符串来计算MD5,俗称:加盐。
6)itertools
操作迭代对象。
①无限迭代
- >>> import itertools;
- >>> natuals = itertools.count(1);
- >>> for n in natuals:
- ... print(n);
- ... if n >10:
- ... break;
- ...
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- >>> cs = itertoos.cycle("ABCD");
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- NameError: name 'itertoos' is not defined
- >>> cs = itertools.cycle("ABCD");
- >>> i = 1;
- >>> for c in cs:
- ... print(c);
- ... i = i +1;
- ... if i > 10:
- ... break;
- ...
- A
- B
- C
- D
- A
- B
- C
- D
- A
- B
- >>> ns = itertools.repeat("A",10);
- >>> for n in ns:
- ... print(n);
- ...
- A
- A
- A
- A
- A
- A
- A
- A
- A
- A
- >>> natuals = itertoos.count(1);
- Traceback (most recent call last):
- File "<stdin>", line 1, in <module>
- NameError: name 'itertoos' is not defined
- >>> natuals = itertools.count(1);
- >>> ns = itertools.takewhile(lambda x:x<10,natuals);
- >>> list(ns);
- [1, 2, 3, 4, 5, 6, 7, 8, 9]
- >>>
②chain()
迭代对象串联
- >>> for c in itertools.chain("ABC","XYZ"):
- ... print(c);
- ...
- A
- B
- C
- X
- Y
- Z
- >>>
③groupby()
相邻的重复元素放一块
- >>> for key,group in itertools.groupby("AABBCCCDDDDDDDAAAAA"):
- ... print(key,list(group));
- ...
- A ['A', 'A']
- B ['B', 'B']
- C ['C', 'C', 'C']
- D ['D', 'D', 'D', 'D', 'D', 'D', 'D']
- A ['A', 'A', 'A', 'A', 'A']
- >>> for key,group in itertools.groupby("AABBCcCDdddddDDDDDaAAAA",lambda c:c.upper()):
- ... print(key,list(group));...
- A ['A', 'A']
- B ['B', 'B']
- C ['C', 'c', 'C']
- D ['D', 'd', 'd', 'd', 'd', 'd', 'D', 'D', 'D', 'D', 'D']
- A ['a', 'A', 'A', 'A', 'A']
- >>>
7)XML
DOM,SAX,没有PULL?
- senrsl@senrsl-T540p:~/test/python3$ vi module/test_sax.py
- senrsl@senrsl-T540p:~/test/python3$ python3 module/test_sax.py
- start_element:ol,attrs:{}
- char_data:
- char_data:
- start_element:li,attrs:{}
- start_element:a,attrs:{'href': 'python'}
- char_data:python
- end_elements:a
- end_elements:li
- char_data:
- char_data:
- start_element:li,attrs:{}
- start_element:a,attrs:{'href': 'ruby'}
- char_data:ruby
- end_elements:a
- end_elements:li
- char_data:
- end_elements:ol
- senrsl@senrsl-T540p:~/test/python3$ cat module/test_sax.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from xml.parsers.expat import ParserCreate;
- class DefaultSaxHandler(object):
- def start_element(self,name,attrs):
- print("start_element:%s,attrs:%s" % (name,str(attrs)));
- def end_element(self,name):
- print("end_elements:%s" % name);
- def char_data(self,text):
- print("char_data:%s" % text);
- xml = r'''<?xml version="1.0"?>
- <ol>
- <li><a href="python">python</a></li>
- <li><a href="ruby">ruby</a></li>
- </ol>
- ''';
- handler = DefaultSaxHandler();
- parser = ParserCreate();
- parser.StartElementHandler =handler.start_element;
- parser.EndElementHandler = handler.end_element;
- parser.CharacterDataHandler = handler.char_data;
- parser.Parse(xml);
- senrsl@senrsl-T540p:~/test/python3$
8)HTMLParser
解析html
- senrsl@senrsl-T540p:~/test/python3$ touch module/test_html_parser.py
- senrsl@senrsl-T540p:~/test/python3$ vi module/test_html_parser.py
- senrsl@senrsl-T540p:~/test/python3$ python3 module/test_html_parser.py
- <html>
- <head>
- </head>
- <body>
- <!-- test html parser -->
- <p>
- Some
- <a>
- html
- </a>
- HTML
-  
- tutorial....
- <br/>
- End
- </p>
- </html>
- senrsl@senrsl-T540p:~/test/python3$ cat module/test_html_parser.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from html.parser import HTMLParser;
- from html.entities import name2codepoint;
- class MyHTMLParser(HTMLParser):
- def handle_starttag(self,tag,attrs):
- print("<%s>" % tag);
- def handle_endtag(self,tag):
- print("</%s>" % tag);
- def handle_startendtag(self,tag,attrs):
- print("<%s/>" % tag);
- def handle_data(self,data):
- print(data);
- def handle_comment(self,data):
- print("<!--%s-->" % data);
- def handle_entityref(self,name):
- print("&%s" % name);
- def handle_charref(self,name):
- print("&#%s" % name);
- parser = MyHTMLParser();
- parser.feed('''<html>
- <head></head>
- <body>
- <!-- test html parser -->
- <p>Some <a href=\"#\">html</a> HTML tutorial....<br/>End</p>
- </html>''');
- senrsl@senrsl-T540p:~/test/python3$
9)urllib
用于URL操作。
①get请求
- senrsl@senrsl-T540p:~/test/python3$ vi module/test_urllib_get.py
- senrsl@senrsl-T540p:~/test/python3$ python3 module/test_urllib_get.py
- 状态: 200 OK
- Server:nginx
- Content-Type:text/html
- Last-Modified:Mon, 27 Jun 2016 05:11:22 GMT
- ETag:"5770b57a-18c4"
- X-Clacks-Overhead:GNU Terry Pratchett
- Strict-Transport-Security:max-age=315360000; includeSubDomains; preload
- Content-Length:6340
- Accept-Ranges:bytes
- Date:Fri, 01 Jul 2016 09:42:58 GMT
- Via:1.1 varnish
- Age:264375
- Connection:close
- X-Served-By:cache-itm7426-ITM
- X-Cache:HIT
- X-Cache-Hits:1
- 数据: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
- "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <title>Copyright — Python 3.5.2 documentation</title>
- <link rel="stylesheet" href="_static/pydoctheme.css" type="text/css" />
- <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
- <script type="text/javascript">
- var DOCUMENTATION_OPTIONS = {
- URL_ROOT: './',
- VERSION: '3.5.2',
- COLLAPSE_INDEX: false,
- FILE_SUFFIX: '.html',
- HAS_SOURCE: true
- };
- </script>
- <script type="text/javascript" src="_static/jquery.js"></script>
- <script type="text/javascript" src="_static/underscore.js"></script>
- <script type="text/javascript" src="_static/doctools.js"></script>
- <script type="text/javascript" src="_static/sidebar.js"></script>
- <link rel="search" type="application/opensearchdescription+xml"
- title="Search within Python 3.5.2 documentation"
- href="_static/opensearch.xml"/>
- <link rel="author" title="About these documents" href="about.html" />
- <link rel="copyright" title="Copyright" href="#" />
- <link rel="top" title="Python 3.5.2 documentation" href="contents.html" />
- <link rel="next" title="History and License" href="license.html" />
- <link rel="prev" title="Dealing with Bugs" href="bugs.html" />
- <link rel="shortcut icon" type="image/png" href="_static/py.png" />
- <script type="text/javascript" src="_static/copybutton.js"></script>
- <script type="text/javascript" src="_static/version_switch.js"></script>
- </head>
- <body role="document">
- <div class="related" role="navigation" aria-label="related navigation">
- <h3>Navigation</h3>
- <ul>
- <li class="right" style="margin-right: 10px">
- <a href="genindex.html" title="General Index"
- accesskey="I">index</a></li>
- <li class="right" >
- <a href="py-modindex.html" title="Python Module Index"
- >modules</a> |</li>
- <li class="right" >
- <a href="license.html" title="History and License"
- accesskey="N">next</a> |</li>
- <li class="right" >
- <a href="bugs.html" title="Dealing with Bugs"
- accesskey="P">previous</a> |</li>
- <li><img src="_static/py.png" alt=""
- style="vertical-align: middle; margin-top: -1px"/></li>
- <li><a href="https://www.python.org/">Python</a> »</li>
- <li>
- <span class="version_switcher_placeholder">3.5.2</span>
- <a href="index.html">Documentation </a> »
- </li>
- </ul>
- </div>
- <div class="document">
- <div class="documentwrapper">
- <div class="bodywrapper">
- <div class="body" role="main">
- <div class="section" id="copyright">
- <h1>Copyright<a class="headerlink" href="#copyright" title="Permalink to this headline">¶</a></h1>
- <p>Python and this documentation is:</p>
- <p>Copyright © 2001-2016 Python Software Foundation. All rights reserved.</p>
- <p>Copyright © 2000 BeOpen.com. All rights reserved.</p>
- <p>Copyright © 1995-2000 Corporation for National Research Initiatives. All rights
- reserved.</p>
- <p>Copyright © 1991-1995 Stichting Mathematisch Centrum. All rights reserved.</p>
- <hr class="docutils" />
- <p>See <a class="reference internal" href="license.html#history-and-license"><span>History and License</span></a> for complete license and permissions information.</p>
- </div>
- </div>
- </div>
- </div>
- <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
- <div class="sphinxsidebarwrapper">
- <h4>Previous topic</h4>
- <p class="topless"><a href="bugs.html"
- title="previous chapter">Dealing with Bugs</a></p>
- <h4>Next topic</h4>
- <p class="topless"><a href="license.html"
- title="next chapter">History and License</a></p>
- <h3>This Page</h3>
- <ul class="this-page-menu">
- <li><a href="bugs.html">Report a Bug</a></li>
- <li><a href="_sources/copyright.txt"
- rel="nofollow">Show Source</a></li>
- </ul>
- <div id="searchbox" style="display: none" role="search">
- <h3>Quick search</h3>
- <form class="search" action="search.html" method="get">
- <input type="text" name="q" />
- <input type="submit" value="Go" />
- <input type="hidden" name="check_keywords" value="yes" />
- <input type="hidden" name="area" value="default" />
- </form>
- <p class="searchtip" style="font-size: 90%">
- Enter search terms or a module, class or function name.
- </p>
- </div>
- <script type="text/javascript">$('#searchbox').show(0);</script>
- </div>
- </div>
- <div class="clearer"></div>
- </div>
- <div class="related" role="navigation" aria-label="related navigation">
- <h3>Navigation</h3>
- <ul>
- <li class="right" style="margin-right: 10px">
- <a href="genindex.html" title="General Index"
- >index</a></li>
- <li class="right" >
- <a href="py-modindex.html" title="Python Module Index"
- >modules</a> |</li>
- <li class="right" >
- <a href="license.html" title="History and License"
- >next</a> |</li>
- <li class="right" >
- <a href="bugs.html" title="Dealing with Bugs"
- >previous</a> |</li>
- <li><img src="_static/py.png" alt=""
- style="vertical-align: middle; margin-top: -1px"/></li>
- <li><a href="https://www.python.org/">Python</a> »</li>
- <li>
- <span class="version_switcher_placeholder">3.5.2</span>
- <a href="index.html">Documentation </a> »
- </li>
- </ul>
- </div>
- <div class="footer">
- © <a href="#">Copyright</a> 2001-2016, Python Software Foundation.
- <br />
- The Python Software Foundation is a non-profit corporation.
- <a href="https://www.python.org/psf/donations/">Please donate.</a>
- <br />
- Last updated on Jun 27, 2016.
- <a href="bugs.html">Found a bug</a>?
- <br />
- Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.3.3.
- </div>
- </body>
- </html>
- senrsl@senrsl-T540p:~/test/python3$ cat module/test_urllib_get.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from urllib import request;
- with request.urlopen("https://docs.python.org/3/copyright.html")as f:
- data = f.read();
- print("状态:",f.status,f.reason);
- for k,v in f.getheaders():
- print("%s:%s" % (k,v));
- print("数据:",data.decode("utf-8"));
- senrsl@senrsl-T540p:~/test/python3$
②模拟浏览器发送get请求
效果:
代码:
- senrsl@senrsl-T540p:~/test/python3$ vi module/test_urllib_request.py
- senrsl@senrsl-T540p:~/test/python3$ python3 module/test_urllib_request.py
- 状态: 200 OK
- cache-control:no-cache, no-store, must-revalidate, pre-check=0, post-check=0
- connection:close
- content-language:en
- content-length:11056
- content-security-policy:default-src 'self'; connect-src 'self'; font-src 'self' data:; frame-src https://*.twitter.com https://*.twimg.com twitter: https://www.google.com; img-src https://twitter.com https://*.twitter.com https://*.twimg.com https://maps.google.com https://www.google-analytics.com https://stats.g.doubleclick.net https://www.google.com data:; media-src https://*.twitter.com https://*.twimg.com https://*.cdn.vine.co; object-src 'self'; script-src 'unsafe-inline' 'unsafe-eval' https://*.twitter.com https://*.twimg.com https://www.google.com https://www.google-analytics.com https://stats.g.doubleclick.net; style-src 'unsafe-inline' https://*.twitter.com https://*.twimg.com; report-uri https://twitter.com/i/csp_report?a=O5SWEZTPOJQWY3A%3D&ro=false;
- content-type:text/html;charset=utf-8
- date:Fri, 01 Jul 2016 09:59:58 GMT
- expires:Tue, 31 Mar 1981 05:00:00 GMT
- last-modified:Fri, 01 Jul 2016 09:59:58 GMT
- pragma:no-cache
- server:tsa_b
- set-cookie:fm=0; Expires=Fri, 01 Jul 2016 09:59:48 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
- set-cookie:_mobile_sess=BAh7ByIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7ADoQX2NzcmZfdG9rZW4iJTE4NGRmMDk4NGM2NmY3YjM5ZDg5YzY4YzgzNTVhOWIz--f33fd98658e35723ca6e566960bf808296649d8c; Expires=Tue, 30 Aug 2016 09:59:58 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
- set-cookie:_twitter_sess=BAh7CCIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo%250ASGFzaHsABjoKQHVzZWR7ADoPY3JlYXRlZF9hdGwrCL2Q5qVVAToHaWQiJTRm%250ANWEzZjQ5MzliMjgzNjljZGRjZDkwNDRiYmQyODUx--a3a54fe95d78a2f274dda00e0166d75a057745e6; Path=/; Domain=.twitter.com; Secure; HTTPOnly
- set-cookie:mobile_metrics_token=146736719833153292; Expires=Sun, 01 Jul 2018 09:59:58 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
- set-cookie:zrca=5; Expires=Sun, 31 Jul 2016 09:59:58 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
- set-cookie:_mb_tk=184df0984c66f7b39d89c68c8355a9b3; Expires=Sun, 03 Jul 2016 09:59:58 GMT; Path=/; Secure; HTTPOnly
- set-cookie:guest_id=v1%3A146736719890570656; Domain=.twitter.com; Path=/; Expires=Sun, 01-Jul-2018 09:59:58 UTC
- strict-transport-security:max-age=631138519
- vary:Accept-Encoding
- x-connection-hash:c0746d4aab68be08e74a67582c8f3ea6
- x-content-type-options:nosniff
- x-frame-options:SAMEORIGIN
- x-response-time:13
- x-transaction:008cc52800e7ad00
- x-twitter-response-tags:BouncerCompliant
- x-xss-protection:1; mode=block
- 数据: <!DOCTYPE html><html class="AppPage CorePage" data-jsaction-events="click,change" data-scribe-page="front" data-scribe-section="front" dir="ltr" jsnamespace="CorePage" lang="en"><meta charset="utf-8"><title>Twitter</title><meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0"><link rel="canonical" href="https://twitter.com/"><meta name="apple-mobile-web-app-capable" content="yes"><meta name="apple-mobile-web-app-status-bar-style" content="black"><link rel="apple-touch-icon" sizes="192x192" href="/app-icon.png"><link rel="icon" sizes="192x192" href="/app-icon.png"><meta name="google-site-verification" content="V0yIS0Ec_o3Ii9KThrCoMCkwTYMMJ_JYx_RSaGhFYvw"><meta name="mobile-web-app-capable" content="yes"><meta name="csrf-protection-token" content="184df0984c66f7b39d89c68c8355a9b3"><meta name="twitter-redirect-url" content="twitter://timeline"><meta name="twitter-redirect-srcs" content="{"pwreset-iphone":true,"android":true,"email":true}"><script>window.goog = new Object(); goog.LOCALE = "en";</script><script src="https://abs.twimg.com/rweb/en/jsaction.bundle.cb41a6176513276b9d73.js"></script><link rel="stylesheet" href="https://abs.twimg.com/rweb/en/common.bundle.5656416b39e41c360528bfbd749b0e12.css"><link rel="stylesheet" href="https://abs.twimg.com/rweb/en/ui-FrontPage.bundle.02e5e85761d97c21e98c1682ba73c091.css"><body class="AppPage-body CorePage-body"><div class=" CoreLayout CoreLayout--fixedHeader CoreLayout--withSplash" ><header class="CoreLayout-header" role="banner"><div class=" AppHeader" ><div class=" AppBar AppBar--inverted u-cf"data-scribe-component="top_bar" jsnamespace="AppBar" ><div class="u-containerWithGutter u-posRelative" jsaction="newTimelineItems:badgeHome"><div class="AppBar-homeCalloutContainer AppBar-homeCalloutContainer--tooltip u-containerWithGutter" id="visit_home_callout"><div class="AppBar-homeCallout">See what's happening on Twitter</div></div><h1 class="u-floatLeft"><a class="AppBar-item AppBar-item--main js-homeIcon AppBar-item--active" aria-label="Twitter" href="/" jsaction="homeNav"><span class="AppBar-itemBadge"></span><span class="AppBar-icon Icon Icon--twitter" role="presentation"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="><svg viewBox="0 0 72 72"><use fill="currentcolor" xlink:href="/i/rw/svg/d59db662aca906e7d567f8c0732ec807/icon#icon-twitter"></use></svg></span></a></h1><div class="u-floatRight"><a class="AppBar-search AppBar-item" aria-label="Search Twitter" href="/search" role="search" jsaction="search"><span class="AppBar-icon Icon Icon--search" role="presentation"><img src="data:image/gif;base64,R0lGODlhBwAJAIAAAP///////yH5BAEKAAEALAAAAAAHAAkAAAIHjI+py+1cAAA7"><svg viewBox="0 0 56 72"><use fill="currentcolor" xlink:href="/i/rw/svg/d59db662aca906e7d567f8c0732ec807/icon#icon-search"></use></svg></span></a><div class="AppBar-hamburger AppBar-item" aria-label="Open Navigation" jsaction="hamburger"><span class="AppBar-icon Icon Icon--drawer" role="presentation"><img src="data:image/gif;base64,R0lGODlhGQAkAPAAAP///wAAACH5BAEKAAAALAAAAAAZACQAAAIchI+py+0Po5y02ouz3rz7D4biSJbmiabqyrZrAQA7"><svg viewBox="0 0 50 72"><use fill="currentcolor" xlink:href="/i/rw/svg/d59db662aca906e7d567f8c0732ec807/icon#icon-drawer"></use></svg></span></div></div></div></div></div></header><main class="CoreLayout-content" role="main"><div class="AppPage-content AppPage-contentSplash u-container"><div class=" Front" jsnamespace="Front"><div class="Front-contentContainer"><span class="Front-icon Icon Icon--twitter" role="presentation"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="><svg viewBox="0 0 72 72"><use fill="currentcolor" xlink:href="/i/rw/svg/d59db662aca906e7d567f8c0732ec807/icon#icon-twitter"></use></svg></span><h2 class="Front-title">Welcome to Twitter</h2><p class="u-textLarge">Get real-time updates about what matters to you.</p></div><div class="Front-buttonContainer"><a class="Front-signupButton Button Button--textBlue Button--invert " href="/signup"><span class="Button-content">Sign up</span></a><a class=" Button Button--default Button--invert " href="/login"><span class="Button-content">Log in</span></a></div></div></div></main></div><div class="SearchSheet FullSheet Sheet u-flex u-posFixed" jsnamespace="SearchSheet" role="dialog"><div class="Sheet-content Sheet-content--scrollable u-flex u-posRelative"><div class="SearchSheet-content u-flexItem"><div class="u-container"><div class=" SearchBox" ><form action="/search" class="SearchBox-form" method="GET"><input class="SearchBox-input u-textXLarge" aria-label="Search query" autocapitalize="off" autocorrect="off" autocomplete="off" name="q" placeholder="Search Twitter" spellcheck="false" type="search"></form></div></div></div></div><div class="Sheet-controls"><div class="Sheet-controlBar"><div class="Sheet-controlsExtra"></div><button class="SearchSheet FullSheet-controlsClose Sheet-controlsClose" aria-label="Close" jsaction="click:close" type="button"><span class="Sheet-closeIcon Icon Icon--close" role="presentation"><img src="data:image/gif;base64,R0lGODlhFwAkAIAAAP///////yH5BAEKAAEALAAAAAAXACQAAAIbjI+py+0Po5y02ouz3rz7D4biSJbmiabqyjIFADs="><svg viewBox="0 0 46 72"><use fill="currentcolor" xlink:href="/i/rw/svg/d59db662aca906e7d567f8c0732ec807/icon#icon-close"></use></svg></span></button></div></div></div><div class="NavigationSheet FullSheet Sheet u-flex u-posFixed" data-scribe-component="dialog_navigation" jsnamespace="NavigationSheet" role="dialog"><div class="Sheet-content Sheet-content--scrollable u-flex u-posRelative"><div class="NavigationSheet-content u-flexItem"><ul class="NavigationSheet-navigation"><li class="NavigationSheet-activeItem"><a href="/" jsaction="home">Home</a></li><li><a href="/signup" jsaction="signup">Sign up</a></li><li><a href="/session/new" jsaction="login">Log in</a></li><li><a href="/search" jsaction="search">Search</a></li><li><a href="https://about.twitter.com" jsaction="about">About</a></li></ul></div></div><div class="Sheet-controls"><div class="Sheet-controlBar"><div class="Sheet-controlsExtra"></div><button class="NavigationSheet FullSheet-controlsClose Sheet-controlsClose" aria-label="Close" jsaction="click:close" type="button"><span class="Sheet-closeIcon Icon Icon--close" role="presentation"><img src="data:image/gif;base64,R0lGODlhFwAkAIAAAP///////yH5BAEKAAEALAAAAAAXACQAAAIbjI+py+0Po5y02ouz3rz7D4biSJbmiabqyjIFADs="><svg viewBox="0 0 46 72"><use fill="currentcolor" xlink:href="/i/rw/svg/d59db662aca906e7d567f8c0732ec807/icon#icon-close"></use></svg></span></button></div></div></div><div class="ModuleOptionsSheet Sheet u-flex u-posFixed" jsnamespace="ModuleOptionsSheet" role="dialog"><div class="Sheet-content u-flex u-posRelative"><div class="ModuleOptionsSheet-content u-flexItem"><ul class="ModuleOptionsSheet-items u-container"><li jsaction="more" class="ModuleOptionsSheet-item"><button>More like this</button></li><li jsaction="less" class="ModuleOptionsSheet-item"><button>Less like this</button></li><li jsaction="close" class="ModuleOptionsSheet-item"><button>Cancel</button></li></ul></div></div></div><div class="SignUpSheet FullSheet Sheet u-flex u-posFixed" jsnamespace="SignUpSheet" role="dialog"><div class="Sheet-content Sheet-content--scrollable u-flex u-posRelative"><div class="SignUpSheet-content u-flexItem"><div class="u-container"><span class="SignUpSheet-twitterIcon Icon Icon--twitter" role="presentation"><img src="data:image/gif;base64,R0lGODlhAQABAIAAAP///////yH5BAEKAAEALAAAAAABAAEAAAICTAEAOw=="><svg viewBox="0 0 72 72"><use fill="currentcolor" xlink:href="/i/rw/svg/d59db662aca906e7d567f8c0732ec807/icon#icon-twitter"></use></svg></span><p class="SignUpSheet-text u-textLarge">Not on Twitter? Sign up, tune into the things you care about, and get updates as they happen.</p><div class="SignUpSheet-buttons u-size1of2"><a class="SignUpSheet-button SignUpSheet-primaryButton u-sizeFull Button Button--textBlue Button--invert " href="/signup"><span class="Button-content">Sign up</span></a><a class="SignUpSheet-button u-sizeFull Button Button--default Button--invert " href="/session/new"><span class="Button-content">Log in</span></a></div></div></div></div><div class="Sheet-controls"><div class="Sheet-controlBar"><div class="Sheet-controlsExtra"></div><button class="SignUpSheet FullSheet-controlsClose Sheet-controlsClose" aria-label="Close" jsaction="click:close" type="button"><span class="Sheet-closeIcon Icon Icon--close" role="presentation"><img src="data:image/gif;base64,R0lGODlhFwAkAIAAAP///////yH5BAEKAAEALAAAAAAXACQAAAIbjI+py+0Po5y02ouz3rz7D4biSJbmiabqyjIFADs="><svg viewBox="0 0 46 72"><use fill="currentcolor" xlink:href="/i/rw/svg/d59db662aca906e7d567f8c0732ec807/icon#icon-close"></use></svg></span></button></div></div></div><div class="MessageDrawer" jsnamespace="MessageDrawer"><div class="MessageDrawer-message" data-name="dismiss">You won't see these kinds of Tweets next time you're here.</div><div class="MessageDrawer-message" data-name="more">You'll see more of these kinds of Tweets every time you're here.</div><div class="MessageDrawer-message" data-name="less">You won't see these kinds of Tweets next time you're here.</div><div class="MessageDrawer-message" data-name="always">You'll see more of these kinds of Tweets every time you're here.</div><div class="MessageDrawer-message" data-name="hide">You won't see these kinds of Tweets next time you're here.</div><div class="MessageDrawer-buttonContainer"><button class=" Button Button--default Button--invert Button--xsmall" jsaction="undo"><span class="Button-content">Undo</span></button></div></div><script type="application/json" id="init-data">{"state":{"pageData":{"canonicalUrl":"https:\/\/twitter.com\/","csrfToken":"184df0984c66f7b39d89c68c8355a9b3","headScripts":["https:\/\/abs.twimg.com\/rweb\/en\/jsaction.bundle.cb41a6176513276b9d73.js"],"lang":"en","messages":[],"nativeAppPath":"timeline","nativeAppURL":"twitter:\/\/timeline","onHomePage":true,"pageName":"front","scripts":["https:\/\/abs.twimg.com\/rweb\/en\/common.bundle.efecdf3ffaed49a24643.js","https:\/\/abs.twimg.com\/rweb\/en\/ui-FrontPage.bundle.5ea1f5418fd93d5a600e.js"],"sectionName":"front","withSubNav":false,"s ubNav":{},"stylesheets":["https:\/\/abs.twimg.com\/rweb\/en\/common.bundle.5656416b39e41c360528bfbd749b0e12.css","https:\/\/abs.twimg.com\/rweb\/en\/ui-FrontPage.bundle.02e5e85761d97c21e98c1682ba73c091.css"],"textDirection":"ltr","title":"Twitter","twitterRefSrcs":"\u007b\"pwreset-iphone\":true,\"android\":true,\"email\":true\u007d","withBadging":false,"withEUCookiePrompt":false,"withOpenInAppPrompt":false,"withSplash":true,"withFastFollow":false,"withRefreshingTimelineCallout":false,"withSignupBar":false}}}</script><script src="https://abs.twimg.com/rweb/en/common.bundle.efecdf3ffaed49a24643.js"></script><script src="https://abs.twimg.com/rweb/en/ui-FrontPage.bundle.5ea1f5418fd93d5a600e.js"></script></body>
- senrsl@senrsl-T540p:~/test/python3$
- senrsl@senrsl-T540p:~/test/python3$ cat module/test_urllib_request.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from urllib import request;
- req = request.Request("https://www.twitter.com/");
- req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25');
- with request.urlopen(req) as f:
- print("状态:",f.status,f.reason);
- for k,v in f.getheaders():
- print("%s:%s" % (k,v));
- print("数据:",f.read().decode("utf-8"));
- senrsl@senrsl-T540p:~/test/python3$
③post请求
- senrsl@senrsl-T540p:~/test/python3$ vi module/test_urllib_post.py
- senrsl@senrsl-T540p:~/test/python3$ python3 module/test_urllib_post.py
- 登陆。。。。
- Email:a
- Password:b
- 状态: 200 OK
- Server : nginx/1.6.1
- Date : Fri, 01 Jul 2016 10:17:49 GMT
- Content-Type : text/html
- Transfer-Encoding : chunked
- Connection : close
- Vary : Accept-Encoding
- Cache-Control : no-cache, must-revalidate
- Expires : Sat, 26 Jul 1997 05:00:00 GMT
- Pragma : no-cache
- Access-Control-Allow-Origin : https://passport.weibo.cn
- Access-Control-Allow-Credentials : true
- DPOOL_HEADER : kotl85
- SINA-LB : aGEuNjIuZzEuYngubGIuc2luYW5vZGUuY29t
- SINA-TS : YTRjNGU0Y2UgMCAwIDAgNCA3NQo=
- 数据: {"retcode":50011002,"msg":"\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef","data":{"username":"a","errline":605}}
- senrsl@senrsl-T540p:~/test/python3$ cat module/test_urllib_post.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from urllib import request,parse;
- print("登陆。。。。");
- email = input("Email:");
- password = input("Password:");
- login_data = parse.urlencode([
- ("username",email),
- ("password",password),
- ("entry","mweibo"),
- ("client_id",""),
- ("savestate","1"),
- ("ec",""),
- ("pagerefer","://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F")
- ]);
- req = request.Request('https://passport.weibo.cn/sso/login');
- req.add_header('Origin', 'https://passport.weibo.cn');
- req.add_header('User-Agent', 'Mozilla/6.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/8.0 Mobile/10A5376e Safari/8536.25');
- req.add_header('Referer', 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F');
- with request.urlopen(req,data=login_data.encode("utf-8")) as f:
- print("状态:",f.status,f.reason);
- for k,v in f.getheaders():
- print("%s : %s" % (k,v));
- print("数据:",f.read().decode("utf-8"));
- senrsl@senrsl-T540p:~/test/python3$
④。。。。
14,第三方模块
都在这里注册https://pypi.python.org/pypi
1)PIL
Python Imaging Library.
Pillow.
①缩放
- >>> from PIL import Image;
- >>> im = Image.open("111111111.png");
- >>> w,h = im.size;
- >>> print("原始图像大小%s,%s" % (w,h));
- 原始图像大小964,787
- >>> im.thumbnail((w//2,h//2));
- >>> print("缩放一半:%s %s" % (w//2,h//2));
- 缩放一半:482 393
- >>> im.save("thumbnailllll.jpg","jpeg");
②模糊
- >>> from PIL import Image,ImageFilter;
- >>> im = Image.open("111111111.png");
- >>> im2 = im.filter(ImageFilter.BLUR);
- >>> im2.save("blur.jpg","jpeg");
- >>>
③生成验证码图片
- >>> from PIL import Image,ImageDraw,ImageFont,ImageFilter;
- >>> import random;
- >>>
- >>> def rndChar():
- ... return chr(random.randint(65,90));
- ...
- >>> def rndColor():
- ... return (random.randint(64,255),random.randint(64,255),random.randint(64,255));
- ...
- >>> def rndColor2():
- ... return (random.randint(32,127),random.randint(32,127),random.randint(32,127));
- ...
- >>> width = 60*4;
- >>> height = 60;
- >>> image = Image.new("RGB",(width,height),(255,255,255));
- >>> font = ImageFont.truetype("Arial.ttf",36);
- >>> draw = ImageDraw.Draw(image);
- >>> for x in range(width):
- ... for y in range(height):
- ... draw.point((x,y),fill=rndColor());
- ...
- >>> for t in range(4):
- ... draw.text((60*t +10,10),rndChar(),font=font,fill=rndColor2());
- ...
- >>> image = image.filter(ImageFilter.BLUR);
- >>> image.save("code.jpg","jpeg");
- >>>
15,virtualenv
用来配置独立的环境
1)安装环境
- senrsl@senrsl-T540p:~/test/python3$ sudo pip3 install virtualenv
- [sudo] password for senrsl:
- Downloading/unpacking virtualenv
- Downloading virtualenv-15.0.2-py2.py3-none-any.whl (1.8MB): 1.8MB downloaded
- Installing collected packages: virtualenv
- Successfully installed virtualenv
- Cleaning up...
- senrsl@senrsl-T540p:~/test/python3$
2)创建独立项目配置独立环境
- senrsl@senrsl-T540p:~/test/python3$ mkdir test_virtualenv
- senrsl@senrsl-T540p:~/test/python3$ cd test_virtualenv/
- senrsl@senrsl-T540p:~/test/python3/test_virtualenv$ virtualenv --no-site-package venv
- Using base prefix '/usr'
- New python executable in /home/senrsl/test/python3/test_virtualenv/venv/bin/python3
- Also creating executable in /home/senrsl/test/python3/test_virtualenv/venv/bin/python
- Installing setuptools, pip, wheel...done.
- senrsl@senrsl-T540p:~/test/python3/test_virtualenv$ source venv/bin/activate
- (venv) senrsl@senrsl-T540p:~/test/python3/test_virtualenv$
3)回正常环境
- (venv) senrsl@senrsl-T540p:~/test/python3/test_virtualenv$ deactivate
- senrsl@senrsl-T540p:~/test/python3/test_virtualenv$
16,图形界面
支持多种图形界面的第三方库,如TK,wxWidgets,Qt,GTK等。
其中支持Tk的Tkinter是自带的。
自带的也得安。。。。
源码:
- senrsl@senrsl-T540p:~/test/python3$ sudo apt-get install python3-tk
- 正在读取软件包列表... 完成
- 正在分析软件包的依赖关系树
- 正在读取状态信息... 完成
- 将会安装下列额外的软件包:
- blt
- 建议安装的软件包:
- blt-demo tix python3-tk-dbg
- 下列【新】软件包将被安装:
- blt python3-tk
- 升级了 0 个软件包,新安装了 2 个软件包,要卸载 0 个软件包,有 406 个软件包未被升级。
- 需要下载 576 kB 的软件包。
- 解压缩后会消耗掉 2,682 kB 的额外空间。
- 您希望继续执行吗? [Y/n] Y
- 获取:1 http://archive.ubuntu.com/ubuntu/ trusty/main blt amd64 2.4z-7ubuntu2 [553 kB]
- 获取:2 http://archive.ubuntu.com/ubuntu/ trusty-updates/main python3-tk amd64 3.4.3-1~14.04.2 [23.5 kB]
- 下载 576 kB,耗时 5秒 (105 kB/s)
- 正在选中未选择的软件包 blt。
- (正在读取数据库 ... 系统当前共安装有 223603 个文件和目录。)
- 正准备解包 .../blt_2.4z-7ubuntu2_amd64.deb ...
- 正在解包 blt (2.4z-7ubuntu2) ...
- 正在选中未选择的软件包 python3-tk。
- 正准备解包 .../python3-tk_3.4.3-1~14.04.2_amd64.deb ...
- 正在解包 python3-tk (3.4.3-1~14.04.2) ...
- 正在处理用于 doc-base (0.10.5) 的触发器 ...
- Processing 1 added doc-base file...
- 正在处理用于 man-db (2.6.7.1-1ubuntu1) 的触发器 ...
- 正在设置 blt (2.4z-7ubuntu2) ...
- 正在设置 python3-tk (3.4.3-1~14.04.2) ...
- 正在处理用于 libc-bin (2.19-0ubuntu6.6) 的触发器 ...
- senrsl@senrsl-T540p:~/test/python3$
- senrsl@senrsl-T540p:~/test/python3$ vi gui/test_tkinter.py
- senrsl@senrsl-T540p:~/test/python3$ python3 gui/test_tkinter.py
- senrsl@senrsl-T540p:~/test/python3$ python3 gui/test_tkinter.py
- senrsl@senrsl-T540p:~/test/python3$
- senrsl@senrsl-T540p:~/test/python3$ cat gui/test_tkinter.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from tkinter import *;
- class Application(Frame):
- def __init__(self,master=None):
- Frame.__init__(self,master);
- self.pack();
- self.createWidgets();
- def createWidgets(self):
- self.helloLable = Label(self,text="Hello,World!");
- self.helloLable.pack();
- self.quitButton = Button(self,text="退出",command=self.quit);
- self.quitButton.pack();
- app = Application();
- app.master.title("你好");
- app.mainloop();
- senrsl@senrsl-T540p:~/test/python3$
然后加个可输入的提示框:
源码:
- senrsl@senrsl-T540p:~/test/python3$ vi gui/test_tkinter2.py
- senrsl@senrsl-T540p:~/test/python3$ python3 gui/test_tkinter2.py
- senrsl@senrsl-T540p:~/test/python3$ cat gui/test_tkinter2.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from tkinter import *;
- import tkinter.messagebox as messagebox;
- class Application(Frame):
- def __init__(self,master=None):
- Frame.__init__(self,master);
- self.pack();
- self.createWidgets();
- def createWidgets(self):
- self.nameInput = Entry(self);
- self.nameInput.pack();
- self.alertButton = Button(self,text="你好啊",command=self.hello);
- self.alertButton.pack();
- def hello(self):
- name = self.nameInput.get() or "世界";
- messagebox.showinfo("消息","提示:%s" % name);
- app = Application();
- app.master.title("你好");
- app.mainloop();
- senrsl@senrsl-T540p:~/test/python3$
17,网络通信
计算机之间进程通信
1)TCP
抓取网页的例子:
- senrsl@senrsl-T540p:~/test/python3$ vi socket/test_tcp.py
- senrsl@senrsl-T540p:~/test/python3$ python3 socket/test_tcp.py
- HTTP/1.1 200 OK
- Date: Mon, 04 Jul 2016 07:06:15 GMT
- Content-Type: text/html
- Content-Length: 14613
- Last-Modified: Tue, 02 Sep 2014 08:55:13 GMT
- Connection: Close
- Vary: Accept-Encoding
- Set-Cookie: BAIDUID=2E1E25FDD3D4AB25B91E49B44DC5E6E2:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
- Set-Cookie: BIDUPSID=2E1E25FDD3D4AB25B91E49B44DC5E6E2; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
- Set-Cookie: PSTM=1467615975; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
- P3P: CP=" OTI DSP COR IVA OUR IND COM "
- Server: BWS/1.1
- X-UA-Compatible: IE=Edge,chrome=1
- Pragma: no-cache
- Cache-control: no-cache
- Accept-Ranges: bytes
- senrsl@senrsl-T540p:~/test/python3$ cat socket/test_tcp.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import socket;
- s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
- s.connect(("www.baidu.com",80));
- s.send(b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n');
- buffer = [];
- while True:
- d = s.recv(1024);
- if d:
- buffer.append(d);
- else:
- break;
- data = b"".join(buffer);
- s.close();
- header,html = data.split(b"\r\n\r\n",1);
- print(header.decode("utf-8"));
- with open("baidu.html","wb") as f:
- f.write(html);
- senrsl@senrsl-T540p:~/test/python3$
服务端跟客户端demo:
服务端源码:
- senrsl@senrsl-T540p:~/test/python3$ cat socket/echo_server.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import socket,threading,time;
- def tcplink(sock,addr):
- print("新连接来自%s %s...." % addr);
- sock.send(b"Welcome!");
- while True:
- data = sock.recv(1024);
- time.sleep(1);
- if not data or data.decode("utf-8")=="exit":
- break;
- sock.send(("hello %s !" % data.decode("utf-8")).encode("utf-8"));
- sock.close();
- print("连接%s %s已关闭" % addr);
- s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
- s.bind(("127.0.0.1",8888));
- s.listen(5);
- print("等待连接。。。。");
- while True:
- sock,addr = s.accept();
- t = threading.Thread(target=tcplink,args=(sock,addr));
- t.start();
- senrsl@senrsl-T540p:~/test/python3$
客户端源码:
- senrsl@senrsl-T540p:~/test/python3$ cat socket/echo_client.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import socket;
- s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
- s.connect(("127.0.0.1",8888));
- print(s.recv(1024).decode("utf-8"));
- for data in [b"a",b"BBBB",b"C11",b"a1234",b"AAA",b"aBcE+"]:
- s.send(data);
- print((s.recv(1024).decode("utf-8")));
- s.send(b"exit");
- s.close();
- senrsl@senrsl-T540p:~/test/python3$
2)UDP
恩,太湖美
Server端:
- senrsl@senrsl-T540p:~/test/python3$ cat socket/echo_udp_server.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import socket;
- s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM);
- s.bind(("127.0.0.1",8888));
- print("绑定UDP,端口8888.。。。");
- while True:
- data,addr = s.recvfrom(1024);
- print("接收%s %s...." % addr);
- s.sendto(("Hello,%s" % data.decode("utf-8")).encode("utf-8"),addr);
- senrsl@senrsl-T540p:~/test/python3$
Client端:
- senrsl@senrsl-T540p:~/test/python3$ cat socket/echo_udp_client.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import socket;
- s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM);
- for data in [b"a",b"BBBB",b"C11",b"a1234",b"AAA",b"aBcE+"]:
- s.sendto(data,("127.0.0.1",8888));
- print((s.recv(1024).decode("utf-8")));
- s.close();
- senrsl@senrsl-T540p:~/test/python3$
18,电子邮件
发件人->MUA->MTA->MTA->若干个MTA->MDA<-MUA<-收件人
MUA:Mail User Agent 邮件用户代理;
MTA:Mail Transfer Agent 邮件传输代理;
MDA:Mail Delivery Agent 邮件投递代理;
发邮件时,MUA和MTA用的SMTP协议。
SMTP:Simple Mail Transfer Protocol.
收邮件时,MUA和MDA可以用POP或IMAP协议。
POP:Post Office Protocol,当前为pop3;
IMAP:Internet Message Access Protocol,当前为imap4;
1)SMTP发送邮件
用163的邮箱不填标题就返回554,shit
源码
- senrsl@senrsl-T540p:~/test/python3$ vi email/test_smtp.py
- senrsl@senrsl-T540p:~/test/python3$ python3 email/test_smtp.py
- From:
- Password:
- To:
- SMTP Server:smtp.163.com
- send: 'ehlo [127.0.1.1]\r\n'
- reply: b'250-mail\r\n'
- reply: b'250-PIPELINING\r\n'
- reply: b'250-AUTH LOGIN PLAIN\r\n'
- reply: b'250-AUTH=LOGIN PLAIN\r\n'
- reply: b'250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2Urfm2BQUCa0xDrUUUUj\r\n'
- reply: b'250-STARTTLS\r\n'
- reply: b'250 8BITMIME\r\n'
- reply: retcode (250); Msg: b'mail\nPIPELINING\nAUTH LOGIN PLAIN\nAUTH=LOGIN PLAIN\ncoremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2Urfm2BQUCa0xDrUUUUj\nSTARTTLS\n8BITMIME'
- send: 'AUTH PLAIN AHNlblJzbEAxNjMuY29tAE15ODYwMzEw\r\n'
- reply: b'235 Authentication successful\r\n'
- reply: retcode (235); Msg: b'Authentication successful'
- send: 'mail FROM:<senRsl@163.com>\r\n'
- reply: b'250 Mail OK\r\n'
- reply: retcode (250); Msg: b'Mail OK'
- send: 'rcpt TO:<senRsl@126.com>\r\n'
- reply: b'250 Mail OK\r\n'
- reply: retcode (250); Msg: b'Mail OK'
- send: 'data\r\n'
- reply: b'354 End data with <CR><LF>.<CR><LF>\r\n'
- reply: retcode (354); Msg: b'End data with <CR><LF>.<CR><LF>'
- data: (354, b'End data with <CR><LF>.<CR><LF>')
- send: b'Content-Type: text/plain; charset="utf-8"\r\nMIME-Version: 1.0\r\nContent-Transfer-Encoding: base64\r\nFrom: =?utf-8?q?python?= <senRsl@163.com>\r\nTo: =?utf-8?b?5a2m5Lmg?= <senRsl@126.com>\r\nSubject: =?utf-8?b?5p2l6IeqU01UUO+8jOayoeagh+mimOWwsTU1NA==?=\r\n\r\naGVsbG8sdGhpcyBlbWFpbCBzZW5kIGJ5IHB5dGhvbu+8gQ==\r\n.\r\n'
- reply: b'250 Mail OK queued as smtp1,C9GowACHD7z2NHpXVTQJAA--.726S2 1467626743\r\n'
- reply: retcode (250); Msg: b'Mail OK queued as smtp1,C9GowACHD7z2NHpXVTQJAA--.726S2 1467626743'
- data: (250, b'Mail OK queued as smtp1,C9GowACHD7z2NHpXVTQJAA--.726S2 1467626743')
- send: 'quit\r\n'
- reply: b'221 Bye\r\n'
- reply: retcode (221); Msg: b'Bye'
- senrsl@senrsl-T540p:~/test/python3$
①发普通:
- senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from email import encoders;
- from email.header import Header;
- from email.mime.text import MIMEText;
- from email.utils import parseaddr,formataddr;
- import smtplib;
- def _format_addr(s):
- name,addr = parseaddr(s);
- return formataddr((Header(name,"utf-8").encode(),addr));
- from_addr = input("From:");
- password = input("Password:");
- to_addr = input("To:");
- smtp_server = input("SMTP Server:");
- msg = MIMEText("hello,this email send by python!","plain","utf-8");
- msg["From"] = _format_addr("python<%s>" % from_addr);
- msg["To"] = _format_addr("学习<%s>" % to_addr);
- msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
- server = smtplib.SMTP(smtp_server,25);
- server.set_debuglevel(1);
- server.login(from_addr,password);
- server.sendmail(from_addr,[to_addr],msg.as_string());
- server.quit();
- senrsl@senrsl-T540p:~/test/python3$
②发html:
- senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_html.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from email import encoders;
- from email.header import Header;
- from email.mime.text import MIMEText;
- from email.utils import parseaddr,formataddr;
- import smtplib;
- def _format_addr(s):
- name,addr = parseaddr(s);
- return formataddr((Header(name,"utf-8").encode(),addr));
- from_addr = input("From:");
- password = input("Password:");
- to_addr = input("To:");
- smtp_server = input("SMTP Server:");
- msg = MIMEText("<html><body>hello,this <b>email</b> send by python!</body></html>","html","utf-8");
- msg["From"] = _format_addr("python<%s>" % from_addr);
- msg["To"] = _format_addr("学习<%s>" % to_addr);
- msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
- server = smtplib.SMTP(smtp_server,25);
- server.set_debuglevel(1);
- server.login(from_addr,password);
- server.sendmail(from_addr,[to_addr],msg.as_string());
- server.quit();
- senrsl@senrsl-T540p:~/test/python3$
③发附件
- senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_annex.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from email import encoders;
- from email.header import Header;
- from email.mime.text import MIMEText;
- from email.mime.multipart import MIMEMultipart;
- from email.mime.base import MIMEBase;
- from email.utils import parseaddr,formataddr;
- import smtplib;
- def _format_addr(s):
- name,addr = parseaddr(s);
- return formataddr((Header(name,"utf-8").encode(),addr));
- from_addr = input("From:");
- password = input("Password:");
- to_addr = input("To:");
- smtp_server = input("SMTP Server:");
- msg = MIMEMultipart();
- #msg = MIMEText("hello,this email send by python!","plain","utf-8");
- msg["From"] = _format_addr("是python<%s>" % from_addr);
- msg["To"] = _format_addr("来自学习<%s>" % to_addr);
- msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
- msg.attach(MIMEText("hello,this email send by python!","plain","utf-8"));
- #添加附件
- with open("/home/senrsl/test/python3/111111111.png","rb") as f:
- mime = MIMEBase("image","png",filename="111111111.png");
- #头信息
- mime.add_header("Content-Dispostion","attachment",filename="111111111.png");
- mime.add_header("Content-ID","<0>");
- mime.add_header("X-Attachment-Id","0");
- #读取附件内容
- mime.set_payload(f.read());
- #编码
- encoders.encode_base64(mime);
- #添加到MIMEMultipart
- msg.attach(mime);
- server = smtplib.SMTP(smtp_server,25);
- server.set_debuglevel(1);
- server.login(from_addr,password);
- server.sendmail(from_addr,[to_addr],msg.as_string());
- server.quit();
- senrsl@senrsl-T540p:~/test/python3$
④发图片
- senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_img.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from email import encoders;
- from email.header import Header;
- from email.mime.text import MIMEText;
- from email.mime.multipart import MIMEMultipart;
- from email.mime.base import MIMEBase;
- from email.utils import parseaddr,formataddr;
- import smtplib;
- def _format_addr(s):
- name,addr = parseaddr(s);
- return formataddr((Header(name,"utf-8").encode(),addr));
- from_addr = input("From:");
- password = input("Password:");
- to_addr = input("To:");
- smtp_server = input("SMTP Server:");
- msg = MIMEMultipart();
- #msg = MIMEText("hello,this email send by python!","plain","utf-8");
- msg["From"] = _format_addr("是python<%s>" % from_addr);
- msg["To"] = _format_addr("来自学习<%s>" % to_addr);
- msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
- msg.attach(MIMEText("<html><body>hello,this email send by python!<br/>图片是<img src='cid:0'/></body></html>","html","utf-8"));
- #添加附件
- with open("/home/senrsl/test/python3/111111111.png","rb") as f:
- mime = MIMEBase("image","png",filename="111111111.png");
- #头信息
- mime.add_header("Content-Dispostion","attachment",filename="111111111.png");
- mime.add_header("Content-ID","<0>");
- mime.add_header("X-Attachment-Id","0");
- #读取附件内容
- mime.set_payload(f.read());
- #编码
- encoders.encode_base64(mime);
- #添加到MIMEMultipart
- msg.attach(mime);
- server = smtplib.SMTP(smtp_server,25);
- server.set_debuglevel(1);
- server.login(from_addr,password);
- server.sendmail(from_addr,[to_addr],msg.as_string());
- server.quit();
- senrsl@senrsl-T540p:~/test/python3$
图片是附件,然后html加img标签,src为cid:0,cid:1。。。。
⑤同时支持html和plain
- senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_html1plain.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from email import encoders;
- from email.header import Header;
- from email.mime.text import MIMEText;
- from email.mime.multipart import MIMEMultipart;
- from email.utils import parseaddr,formataddr;
- import smtplib;
- def _format_addr(s):
- name,addr = parseaddr(s);
- return formataddr((Header(name,"utf-8").encode(),addr));
- from_addr = input("From:");
- password = input("Password:");
- to_addr = input("To:");
- smtp_server = input("SMTP Server:");
- msg = MIMEMultipart("alternative");
- msg["From"] = _format_addr("python<%s>" % from_addr);
- msg["To"] = _format_addr("学习<%s>" % to_addr);
- msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
- msg.attach(MIMEText("hello,this如果客户端版本旧不支持html就显示这个文本 ","plain","utf-8"));
- msg.attach(MIMEText("<html><body>hello,this <b>email</b> send by python!</body></html>","html","utf-8"));
- server = smtplib.SMTP(smtp_server,25);
- server.set_debuglevel(1);
- server.login(from_addr,password);
- server.sendmail(from_addr,[to_addr],msg.as_string());
- server.quit();
- senrsl@senrsl-T540p:~/test/python3$
⑥加密smtp
163连不上服务器,可能还得需要证书吧。。。。
- senrsl@senrsl-T540p:~/test/python3$ python3 email/test_smtp_ttls.py
- 。。。。
- Traceback (most recent call last):
- File "email/test_smtp_ttls.py", line 30, in <module>
- server = smtplib.SMTP(smtp_server,smtp_port);
- File "/usr/lib/python3.4/smtplib.py", line 242, in __init__
- (code, msg) = self.connect(host, port)
- File "/usr/lib/python3.4/smtplib.py", line 323, in connect
- (code, msg) = self.getreply()
- File "/usr/lib/python3.4/smtplib.py", line 376, in getreply
- raise SMTPServerDisconnected("Connection unexpectedly closed")
- smtplib.SMTPServerDisconnected: Connection unexpectedly closed
- senrsl@senrsl-T540p:~/test/python3$ vi email/test_smtp_ttls.py
- senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_ttls.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from email import encoders;
- from email.header import Header;
- from email.mime.text import MIMEText;
- from email.utils import parseaddr,formataddr;
- import smtplib;
- def _format_addr(s):
- name,addr = parseaddr(s);
- return formataddr((Header(name,"utf-8").encode(),addr));
- from_addr = input("From:");
- password = input("Password:");
- to_addr = input("To:");
- smtp_server = "smtp.163.com";
- smtp_port = 465;#465/994
- msg = MIMEText("hello,this email send by python!","plain","utf-8");
- msg["From"] = _format_addr("python<%s>" % from_addr);
- msg["To"] = _format_addr("学习<%s>" % to_addr);
- msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
- server = smtplib.SMTP(smtp_server,smtp_port);
- server.starttls();
- server.set_debuglevel(1);
- server.login(from_addr,password);
- server.sendmail(from_addr,[to_addr],msg.as_string());
- server.quit();
- senrsl@senrsl-T540p:~/test/python3$
2)POP3收取邮件
①用poplib把邮件原始文本下载到本地;
②用email解析原始文本,还原为邮件对象。
那个循环是从头里取,不要改文字啊。。。。
- senrsl@senrsl-T540p:~/test/python3$ cat email/test_pop3_resovle.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import poplib;
- from email.parser import Parser;
- from email.header import decode_header;
- from email.utils import parseaddr;
- def decode_str(s):
- value,charset = decode_header(s)[0];
- if charset:
- value = value.decode(charset);
- return value;
- def guess_charset(msg):
- charset = msg.get_charset();
- if charset is None:
- content_type = msg.get("Content-Type","").lower();
- pos = content_type.find("charset=");
- if pos >=0:
- charset = content_type[pos+8:].strip();
- return charset;
- def print_info(msg,indent=0):
- if indent ==0:
- for header in ["From","To","Subject"]:
- value = msg.get(header,"");
- print("header的value是:",value);
- if value:
- if header == "Subject":
- value = decode_str(value);
- else:
- hdr,addr = parseaddr(value);
- name = decode_str(hdr);
- value = u"%s <%s>" % (name,addr);
- print("%s %s: %s" % (' ' * indent,header,value));
- if (msg.is_multipart()):
- parts = msg.get_payload();
- for n,part in enumerate(path):
- print("%spart %s" % (" " * indent,n ));
- print("%s-----------" % (" " * indent));
- print_info(part,indent+1);
- else:
- content_type = msg.get_content_type();
- if content_type == "text/plain" or content_type == "text/html":
- content = msg.get_payload(decode=True);
- charset = guess_charset(msg);
- if charset:
- content = content.decode(charset);
- print("%s 内容: %s" % (" " * indent,content+"...."));
- else:
- print("%s Attachment:%s" % (" " * indent,content_type));
- email = input("邮箱:");
- password = input("密码: ");
- pop3_server = input("POP服务器地址:");
- #连接到pop3服务器
- server = poplib.POP3(pop3_server);
- #调试信息
- server.set_debuglevel(1);
- #打印pop3的欢迎文字
- print(server.getwelcome().decode("utf-8"));
- #身份认证
- server.user(email);
- server.pass_(password);
- #stat()返回邮件数量和占用空间
- print("消息 %s,大小:%s" % server.stat());
- #所有邮件编号
- resp,mails,octets = server.list();
- #可以查看返回的编号列表类似
- #print(mails);
- #获取最后一封邮件
- index = len(mails);
- resp,lines,octets = server.retr(index);
- #lines存储邮件的原始文本的每一行
- #可以获得整个邮件的原始文本
- msg_content = b"\r\n".join(lines).decode("utf-8");
- #解析邮件
- msg = Parser().parsestr(msg_content);
- print_info(msg);
- #可以根据邮件索引直接从服务器删除邮件
- #server.dele(index);
- #关闭连接
- server.quit();
- senrsl@senrsl-T540p:~/test/python3$
19,数据库
网状数据库-->层次数据库-->关系数据库
1)SQLite
内置了sqlite3
- senrsl@senrsl-T540p:~/test/python3$ mkdir db
- senrsl@senrsl-T540p:~/test/python3$ cd db
- senrsl@senrsl-T540p:~/test/python3/db$ python3
- Python 3.4.3 (default, Oct 14 2015, 20:28:29)
- [GCC 4.8.4] on linux
- Type "help", "copyright", "credits" or "license" for more information.
- >>>
- >>>
- >>> import sqlite3;
- >>> conn = sqlite3.connect("test.db");
- >>> cursor = conn.cursor();
- >>> cursor.execute("create table user(id varchar(20) primary key,name varchar(20))");
- <sqlite3.Cursor object at 0x7f354cd722d0>
- >>> cursor.execute("insert into user (id,name) values (\"1\",\"fuck\")");
- <sqlite3.Cursor object at 0x7f354cd722d0>
- >>> cursor.rowcount;
- 1
- >>> cursor.close();
- >>> conn.commit();
- >>> conn.close();
- >>>
- >>> conn = sqlite3.connect("test.db");
- >>> cursor = conn.cursor();
- >>> cursor.execute("select * from user where id = ?",("1"));
- <sqlite3.Cursor object at 0x7f354b6c0f80>
- >>> values = cursor.fetchall();
- >>> values
- [('1', 'fuck')]
- >>> cursor.close();
- >>> conn.close();
- >>>
2)MySQL
需要安装驱动
然后手动下载
- senrsl@senrsl-T540p:~/test/python3/db$ pip3 install mysql-connector-python --allow-external mysql-connector-python
- Downloading/unpacking mysql-connector-python
- Could not find any downloads that satisfy the requirement mysql-connector-python
- Cleaning up...
- No distributions at all found for mysql-connector-python
- Storing debug log for failure in /home/senrsl/.pip/pip.log
- senrsl@senrsl-T540p:~/test/python3/db$
https://pypi.python.org/pypi/mysql-connector-python/2.0.4
解压,执行
一开始怎么都找不到,教程是 sudo python setup....
- senrsl@senrsl-T540p:~/test/python3/db/mysql-connector-python-2.0.4$ sudo python3 setup.py install
- [sudo] password for senrsl:
- ....
现在的命令环境是python3....
就好了
数据库用的视频聊天demo服务器上的测试数据库
- senrsl@senrsl-T540p:~/test/python3/db$ python3
- Python 3.4.3 (default, Oct 14 2015, 20:28:29)
- [GCC 4.8.4] on linux
- Type "help", "copyright", "credits" or "license" for more information.
- >>>
- >>> import mysql.connector;
- >>> conn = mysql.connector.connect(host="10.1.8.102",user="root",password="0123",database="test");
- >>> cursor = conn.cursor();
- >>> cursor.execute("create table user(id varchar(20) primary key,name varchar(20))");
- >>> cursor.execute("insert into user(id,name) values(%s,%s)",["1","fuck"]);
- >>> cursor.rowcount
- 1
- >>> conn.commit();
- >>> cursor.close();
- True
- >>>
- >>> cursor = conn.cursor();
- >>> cursor.execute("select * from user where id = %s",("1",));
- >>> values = cursor.fetchall();
- >>> values
- [('1', 'fuck')]
- >>> cursor.close();
- True
- >>> conn.close();
- >>>
3)使用SQLAlchemy框架
这是一个ORM框架
ORM:Object-Relational Mapping.
安装:
使用:
- senrsl@senrsl-T540p:~/test/python3/db$ sudo pip3 install sqlalchemy
- [sudo] password for senrsl:
一个封装
- >>> from sqlalchemy import Column,String,create_engine;
- >>> from sqlalchemy.orm import sessionmaker;
- >>> from sqlalchemy.ext.declarative import declarative_base;
- >>>
- >>> Base = declarative_base();
- >>> class User(Base):
- ... __tablename__ = "user";
- ... id = Column(String(20),primary_key=True);
- ... name = Column(String(20));
- ...
- >>> engine = create_engine("mysql+mysqlconnector://root:0123@10.1.8.102:3306/test");
- >>> DBSession = sessionmaker(bind=engine);
- >>>
- >>> session = DBSession();
- >>> new_user = User(id="3",name="啊啊");
- >>> session.add(new_user);
- >>> session.commit();
- >>> session.close();
- >>>
- >>> session = DBSession();
- >>> user = session.query(User).filter(User.id=="3").one();
- >>> print("type",type(user));
- type <class '__main__.User'>
- >>> print("name:",user.name);
- name: 啊啊
- >>> session.close();
- >>>
20,Web
CS/BS
BS:
静态Web-->CGI(Common Gateway Interface,C/C++)-->>ASP/JSP/PHP-->MVC
CSS:Cascading Style Sheets,层叠样式表
WSGI:Web Server Gateway Interface.
1)WSGI服务
效果:
- senrsl@senrsl-T540p:~/test/python3$ python3 web/test_wsgi_server.py
- 模块wsgiref,纯python编写的WSGI服务器的参考实现
- 所谓"参考实现"是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用
- 服务运行在8080上。。。。
- 127.0.0.1 - - [06/Jul/2016 17:09:26] "GET / HTTP/1.1" 200 19
- 127.0.0.1 - - [06/Jul/2016 17:09:26] "GET /favicon.ico HTTP/1.1" 200 27
- 127.0.0.1 - - [06/Jul/2016 17:09:43] "GET /aaaaaa HTTP/1.1" 200 22
- 127.0.0.1 - - [06/Jul/2016 17:09:43] "GET /favicon.ico HTTP/1.1" 200 27
- ^Z
- [1]+ 已停止 python3 web/test_wsgi_server.py
- senrsl@senrsl-T540p:~/test/python3$ cat web/test_wsgi_server.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- print("模块wsgiref,纯python编写的WSGI服务器的参考实现");
- print("所谓"参考实现"是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使 用");
- from wsgiref.simple_server import make_server;
- from test_wsgi_hello import application;
- #IP地址,端口,处理函数
- httpd = make_server("",8080,application);
- print("服务运行在%s上。。。。" % 8080);
- #启动监听
- httpd.serve_forever();
- senrsl@senrsl-T540p:~/test/python3$ cat web/test_wsgi_hello.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- def application(environ,start_response):
- start_response("200 OK",[("Content-Type","text/html")]);
- body = "<h1>Hello,%s!</h1>" % (environ["PATH_INFO"][1:] or "web");
- # return [b"<h1>Hello,web!</h1>"];
- return [body.encode("utf-8")];
- senrsl@senrsl-T540p:~/test/python3$
2)框架Flask
安装库:
- senrsl@senrsl-T540p:~/test/python3$ sudo pip3 install flask
使用:
常见的Web框架:
- senrsl@senrsl-T540p:~/test/python3$ vi web/test_flask.py
- senrsl@senrsl-T540p:~/test/python3$ python3 web/test_flask.py
- * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
- 127.0.0.1 - - [06/Jul/2016 17:32:42] "GET / HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:32:42] "GET /favicon.ico HTTP/1.1" 404 -
- 127.0.0.1 - - [06/Jul/2016 17:32:48] "GET / HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:05] "GET /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:11] "POST /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:13] "GET /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:28] "POST /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:29] "GET /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:35] "POST /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:37] "GET /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:55] "POST /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 17:33:57] "GET /signin HTTP/1.1" 200 -
- ^Z
- [2]+ 已停止 python3 web/test_flask.py
- senrsl@senrsl-T540p:~/test/python3$ cat web/test_flask.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from flask import Flask;
- from flask import request;
- app = Flask(__name__);
- @app.route("/",methods=["GET","POST"])
- def home():
- return "<h1>Home</h1>";
- @app.route("/signin",methods=["GET"])
- def signin_form():
- return """<form action='/signin' method='post'>
- <p><input name='username'/></p>
- <p><input name='password' type='password'/></p>
- <p><button type='submit'>登陆</button></p>
- </form>""";
- @app.route("/signin",methods=["POST"])
- def signin():
- if request.form["username"]=="admin" and request.form["password"] =="passwd":
- return "<h3>Hello,admin</h3>";
- return "<h3>密码错误</h3>";
- if __name__ == "__main__":
- app.run();
- senrsl@senrsl-T540p:~/test/python3$
Django,web.py,Bottle,Tomado.
3)模板Jinja2
要看目录结构,不看结构浪费好久
常见的模板还有:
- senrsl@senrsl-T540p:~$ cd test/python3/
- senrsl@senrsl-T540p:~/test/python3$ python3 web/test_flask_mvc.py
- * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
- 127.0.0.1 - - [06/Jul/2016 20:32:53] "GET / HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 20:32:59] "GET /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 20:33:01] "POST /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 20:33:04] "POST /signin HTTP/1.1" 200 -
- 127.0.0.1 - - [06/Jul/2016 20:33:09] "POST /signin HTTP/1.1" 200 -
- ^Z
- [1]+ 已停止 python3 web/test_flask_mvc.py
- senrsl@senrsl-T540p:~/test/python3$ cat web/test_flask_mvc.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- from flask import Flask,request,render_template
- app = Flask(__name__);
- @app.route("/",methods=["GET","POST"])
- def home():
- return render_template("test_flask_mvc_home.html");
- @app.route("/signin",methods=["GET"])
- def signin_form():
- return render_template("test_flask_mvc_form.html");
- @app.route("/signin",methods=["POST"])
- def signin():
- username = request.form["username"];
- password = request.form["password"];
- if username == "admin" and password=="passwd":
- return render_template("test_flask_mvc_sigin_suss.html",username=username);
- return render_template("test_flask_mvc_form.html",message="错误用户名或密 码",username=username);
- if __name__ =="__main__":
- app.run();
- senrsl@senrsl-T540p:~/test/python3$ cat web/templates/test_flask_mvc_home.html
- <html>
- <head>
- <title>Home</title>
- </head>
- <body>
- <h1 style="font-style:italic">Home</h1>
- </body>
- </html>
- senrsl@senrsl-T540p:~/test/python3$ cat web/templates/test_flask_mvc_sigin_suss.html
- <html>
- <head>
- <title>Welcome, {{ username }}</title>
- </head>
- <body>
- <p>Welcome, {{ username }}!</p>
- </body>
- </html>
- senrsl@senrsl-T540p:~/test/python3$ cat web/templates/test_flask_mvc_form.html
- <html>
- <head>
- <title>Please Sign In</title>
- </head>
- <body>
- {% if message %}
- <p style="color:red">{{ message }}</p>
- {% endif %}
- <form action="/signin" method="post">
- <legend>Please sign in:</legend>
- <p><input name="username" placeholder="Username" value="{{ username }}"></p>
- <p><input name="password" placeholder="Password" type="password"></p>
- <p><button type="submit">Sign In</button></p>
- </form>
- </body>
- </html>
- senrsl@senrsl-T540p:~/test/python3$
Mako,Cheetah,Django等。。。。
21,异步IO
1)协程
微线程,纤程,coroutine [kəru:'ti:n ]。
进程:
进程之间不共享任何状态,进程的调度由操作系统完成,每个进程都有自己独立的内存空间,进程间通讯主要是通过信号传递的方式来实现的,实现方 式有多种,信号量、管道、事件等,任何一种方式的通讯效率都需要过内核,导致通讯效率比较低。由于是独立的内存空间,上下文切换的时候需要保 存先调用栈的信息、cpu各寄存器的信息、虚拟内存、以及打开的相关句柄等信息,所以导致上下文进程间切换开销很大,通讯麻烦。
线程:
线程之间共享变量,解决了通讯麻烦的问题,但是对于变量的访问需要锁,线程的调度主要也是有操作系统完成,一个进程可以拥有多个线程,但是其 中每个线程会共享父进程像操作系统申请资源,这个包括虚拟内存、文件等,由于是共享资源,所以创建线程所需要的系统资源占用比进程小很多,相 应的可创建的线程数量也变得相对多很多。线程时间的通讯除了可以使用进程之间通讯的方式以外还可以通过共享内存的方式进行通信,所以这个速度 比通过内核要快很多。另外在调度方面也是由于内存是共享的,所以上下文切换的时候需要保存的东西就像对少一些,这样一来上下文的切换也变得高 效。
协程:
协程的调度完全由用户控制,一个线程可以有多个协程,用户创建了几个线程,然后每个线程都是循环按照指定的任务清单顺序完成不同的任务,当任 务被堵塞的时候执行下一个任务,当恢复的时候再回来执行这个任务,任务之间的切换只需要保存每个任务的上下文内容,就像直接操作栈一样的,这 样就完全没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快;另外协程还需要保证是非堵塞的且没有相互依赖,协程基本上 不能同步通讯,多采用一步的消息通讯,效率比较高。
这是协程的一个示例:
- senrsl@senrsl-T540p:~/test/python3$ python3
- Python 3.4.3 (default, Oct 14 2015, 20:28:29)
- [GCC 4.8.4] on linux
- Type "help", "copyright", "credits" or "license" for more information.
- >>> def consumer():
- ... r = "";
- ... while True:
- ... n = yield r;
- ... if not n:
- ... return;
- ... print("[消费者]Consuming %s...." % n);
- ... r = "200 OK";
- ...
- >>> def produce(c):
- ... c.send(None);
- ... n = 0;
- ... while n <5:
- ... n = n+1;
- ... print("[生产者]Producing %s...." % n);
- ... r = c.send(n);
- ... print("[生产者2]Consumer return %s" % r);
- ... c.close();
- ...
- >>> c = consumer();
- >>> produce(c);
- [生产者]Producing 1....
- [消费者]Consuming 1....
- [生产者2]Consumer return 200 OK
- [生产者]Producing 2....
- [消费者]Consuming 2....
- [生产者2]Consumer return 200 OK
- [生产者]Producing 3....
- [消费者]Consuming 3....
- [生产者2]Consumer return 200 OK
- [生产者]Producing 4....
- [消费者]Consuming 4....
- [生产者2]Consumer return 200 OK
- [生产者]Producing 5....
- [消费者]Consuming 5....
- [生产者2]Consumer return 200 OK
- >>>
2)asyncio
python3.4引入,内置对异步IO支持
demo:
用Task封装看效果:
- >>> import asyncio;
- >>> @asyncio.coroutine
- ... def hello():
- ... print("hello world!");
- ... r = yield from asyncio.sleep(1);
- ... print("hello again!");
- ...
- >>> loop = asyncio.get_event_loop();
- >>> loop.run_until_complete(hello());
- hello world!
- hello again!
- >>> loop.close();
- >>>
- senrsl@senrsl-T540p:~/test/python3$ python3
- Python 3.4.3 (default, Oct 14 2015, 20:28:29)
- [GCC 4.8.4] on linux
- Type "help", "copyright", "credits" or "license" for more information.
- >>>
- >>> import threading;
- >>> import asyncio;
- >>> @asyncio.coroutine
- ... def hello():
- ... print("Hello world %s !" % threading.currentThread());
- ... yield from asyncio.sleep(1);
- ... print("Hello again %s !" % threading.currentThread());
- ...
- >>> loop = asyncio.get_event_loop();
- >>> tasks = [hello(),hello()];
- >>> loop.run_until_complete(asyncio.wait(tasks));
- Hello world <_MainThread(MainThread, started 140178258724672)> !
- Hello world <_MainThread(MainThread, started 140178258724672)> !
- Hello again <_MainThread(MainThread, started 140178258724672)> !
- Hello again <_MainThread(MainThread, started 140178258724672)> !
- ({<Task finished coro=<hello() done, defined at <stdin>:1> result=None>, <Task finished coro=<hello() done, defined at <stdin>:1> result=None>}, set())
- >>> loop.close();
- >>>
异步获取仨网站的首页:
少写一个空格找半天。。。。
- senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_asynicio.py
- wget www.sohu.com....
- wget www.sina.com.cn....
- wget www.163.com....
- www.sohu.com header > HTTP/1.1 200 OK
- www.sohu.com header > Content-Type: text/html
- www.sohu.com header > Content-Length: 91589
- www.sohu.com header > Connection: close
- www.sohu.com header > Date: Thu, 07 Jul 2016 10:28:48 GMT
- www.sohu.com header > Server: SWS
- www.sohu.com header > Vary: Accept-Encoding
- www.sohu.com header > Cache-Control: no-transform, max-age=120
- www.sohu.com header > Expires: Thu, 07 Jul 2016 10:30:48 GMT
- www.sohu.com header > Last-Modified: Thu, 07 Jul 2016 10:28:10 GMT
- www.sohu.com header > Content-Encoding: gzip
- www.sohu.com header > X-RS: 10587158.19762208.11340962
- www.sohu.com header > FSS-Cache: HIT from 7965678.14519288.8719442
- www.sohu.com header > FSS-Proxy: Powered by 2722718.4033448.3476402
- www.163.com header > HTTP/1.0 302 Moved Temporarily
- www.163.com header > Server: Cdn Cache Server V2.0
- www.163.com header > Date: Thu, 07 Jul 2016 10:29:45 GMT
- www.163.com header > Content-Length: 0
- www.163.com header > Location: http://www.163.com/special/0077jt/error_isp.html
- www.163.com header > Connection: close
- www.sina.com.cn header > HTTP/1.1 200 OK
- www.sina.com.cn header > Content-Type: text/html
- www.sina.com.cn header > Vary: Accept-Encoding
- www.sina.com.cn header > X-Powered-By: shci_v1.03
- www.sina.com.cn header > Server: nginx
- www.sina.com.cn header > Date: Thu, 07 Jul 2016 10:29:12 GMT
- www.sina.com.cn header > Last-Modified: Thu, 07 Jul 2016 10:27:53 GMT
- www.sina.com.cn header > Expires: Thu, 07 Jul 2016 10:30:12 GMT
- www.sina.com.cn header > Cache-Control: max-age=60
- www.sina.com.cn header > Age: 33
- www.sina.com.cn header > Content-Length: 600183
- www.sina.com.cn header > X-Cache: HIT from cnc.tj.1cf2.93.spool.sina.com.cn
- www.sina.com.cn header > Connection: close
- senrsl@senrsl-T540p:~/test/python3$ cat asyncio/test_asynicio.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import asyncio;
- @asyncio.coroutine
- def wget(host):
- print("wget %s...." % host);
- connect = asyncio.open_connection(host,80);
- reader,writer = yield from connect;
- header = "GET / HTTP/1.0\r\nHost: %s\r\n\r\n" % host;
- writer.write(header.encode("utf-8"));
- yield from writer.drain();
- while True:
- line = yield from reader.readline();
- if line == b"\r\n":
- break;
- print("%s header > %s" % (host,line.decode("utf-8").rstrip()));
- writer.close();
- loop = asyncio.get_event_loop();
- tasks = [wget(host) for host in ["www.sina.com.cn","www.sohu.com","www.163.com"]];
- loop.run_until_complete(asyncio.wait(tasks));
- loop.close();
- senrsl@senrsl-T540p:~/test/python3$
回到第一节重新看。。。。
好像有点明白了
- senrsl@senrsl-T540p:~/test/python3$ vi asyncio/test_coroutine.py
- senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_coroutine.py
- [生产者]1....
- [消费者]1....
- [生产者] return 200 OK......
- [生产者]2....
- [消费者]2....
- [生产者] return 200 OK......
- [生产者]3....
- [消费者]3....
- [生产者] return 200 OK......
- [生产者]4....
- [消费者]4....
- [生产者] return 200 OK......
- [生产者]5....
- [消费者]5....
- [生产者] return 200 OK......
- senrsl@senrsl-T540p:~/test/python3$
- senrsl@senrsl-T540p:~/test/python3$ vi asyncio/test_asyncio_demo.py
- senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_asyncio_demo.py
- hello,world!!!!!
- hello again!
- senrsl@senrsl-T540p:~/test/python3$
- senrsl@senrsl-T540p:~/test/python3$ cp asyncio/test_asyncio_demo.py asyncio/test_asyncio_thread.py
- senrsl@senrsl-T540p:~/test/python3$ vi asyncio/test_asyncio_thread.py
- senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_asyncio_thread.py
- hello,world!!!!! <_MainThread(MainThread, started 140340961548096)>
- hello,world!!!!! <_MainThread(MainThread, started 140340961548096)>
- hello again! <_MainThread(MainThread, started 140340961548096)>
- hello again! <_MainThread(MainThread, started 140340961548096)>
- senrsl@senrsl-T540p:~/test/python3$
貌似一条线程,顺序执行下的非阻塞任务。。。。
3)async/await
从3.5之后引入了新的语法async和await,最大的好处是单词短了好认
①把@asyncio.coroutine这个注解替换成async这个关键字;
②把yield from替换成await;
即可无痛升级到3.5短版。
4)aiohttp
基于asyncio实现的http框架。
安装:
执行:
- senrsl@senrsl-T540p:~/test/python3$ sudo pip3 install aiohttp
效果:
- senrsl@senrsl-T540p:~$ cd test/python3/
- senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_aiohttp.py
- Server started at http://127.0.0.1:8888....
- ^Z
- [1]+ 已停止 python3 asyncio/test_aiohttp.py
- senrsl@senrsl-T540p:~/test/python3$ cat asyncio/test_aiohttp.py
- #!/usr/bin/env python3
- # -*- coding:utf-8 -*-
- import asyncio;
- from aiohttp import web;
- @asyncio.coroutine
- def index(request):
- yield from asyncio.sleep(0.5);
- return web.Response(body=b"<h1>Index</h1>");
- @asyncio.coroutine
- def hello(request):
- yield from asyncio.sleep(0.5);
- text = "<h1>你好%s</h1>" % request.match_info["name"];
- return web.Response(body=text.encode("utf-8"));
- @asyncio.coroutine
- def init(loop):
- app = web.Application(loop=loop);
- app.router.add_route("GET","/",index);
- app.router.add_route("GET","/hello/{name}",hello);
- srv = yield from loop.create_server(app.make_handler(),"127.0.0.1",8888);
- print("Server started at http://127.0.0.1:8888....");
- return srv;
- loop = asyncio.get_event_loop();
- loop.run_until_complete(init(loop));
- loop.run_forever();
- senrsl@senrsl-T540p:~/test/python3$
教程终于看完了。。。。
教程里的项目实战准备。
2016年07月08日17:52:20
--
senRsl
2016年06月29日10:15:34
2016年06月29日10:15:34
没有评论 :
发表评论