東川印記

一本東川,笑看爭龍斗虎;寰茫兦者,度橫佰昧人生。

python3学习之进阶篇

2016年7月8日星期五





10,IO
输入输出
同步异步

1)文件读写
①读
try或with打开文件;
read或readline读取文件;
  1. senrsl@senrsl-T540p:~/test/python3$ touch tmp
  2. senrsl@senrsl-T540p:~/test/python3$ echo -e "1\n啊\n3\n\t4\n5">>tmp
  3. senrsl@senrsl-T540p:~/test/python3$ python3
  4. Python 3.4.3 (default, Oct 14 2015, 20:28:29)
  5. [GCC 4.8.4] on linux
  6. Type "help", "copyright", "credits" or "license" for more information.
  7. >>> def readFileTry():
  8. ...     try:
  9. ...         f = open("tmp","r");
  10. ...         print(f.read());
  11. ...     finally:
  12. ...         if f:
  13. ...             f.close();
  14. ...
  15. >>> readFileTry();
  16. 1
  17. 3
  18.     4
  19. 5
  20. >>> def readFileWith():
  21. ...     with open("tmp","r") as f:
  22. ...         print(f.read());
  23. ...
  24. >>> readFileWith();
  25. 1
  26. 3
  27.     4
  28. 5
  29. >>>
  30. >>> def readFileWithASize():
  31. ...     with open("tmp","r") as f:
  32. ...         for size in f.read(4):
  33. ...             print(size);
  34. ...
  35. >>> readFileWithASize();
  36. 1
  37. >>> def readFileWithASize():
  38. ...     with open("tmp","r") as f:
  39. ...         print(f.read(10));
  40. ...
  41. >>> readFileWithASize();
  42. 1
  43. 3
  44.     4
  45. 5
  46. >>> def readFileWithASize():
  47. ...     with open("tmp","r") as f:
  48. ...         print(f.read(3));
  49. ...
  50. >>> readFileWithASize();
  51. 1
  52. >>> def readFileWithLine():
  53. ...     with open("tmp","r") as f:
  54. ...         for line in f.readlines():
  55. ...             print(line.strip());
  56. ...
  57. >>> readFileWithLine();
  58. 1
  59. 3
  60. 4
  61. 5
  62. >>>
有read()方法的对象,叫做file-like Object.类文件对象。

语法:
f = open("tmp","r",encoding="gbk",errors="ignore");
指向变量 = open("目标文件","打开模式",encoding="打开编码",errors="出现错误怎么办");
打开模式:r为只读,w为覆盖写,a为追加写,b为二进制

②写
  1. >>> def writeFileTry():
  2. ...     f = open("tmp","w");
  3. ...     f.write("fuck");
  4. ...     f.close();
  5. ...
  6. >>> writeFileTry();
  7. >>> readFileTry();
  8. fuck
  9. >>> def writeFileWith():
  10. ...     with open("tmp","w") as f:
  11. ...         f.write("fuck2");
  12. ...
  13. >>> writeFileWith();
  14. >>> readFileWith();
  15. fuck2
  16. >>> def writeFileWith():
  17. ...     with open("tmp","a") as f:
  18. ...         f.write("fuck22222222");
  19. ...
  20. >>> readFileWith();
  21. fuck2
  22. >>> writeFileWith();
  23. >>> readFileWith();
  24. fuck2fuck22222222
  25. >>> writeFileWith();
  26. >>> writeFileWith();
  27. >>> readFileWith();
  28. fuck2fuck22222222fuck22222222fuck22222222
  29. >>>

2)StringIO和BytesIO
封了俩工具出来

①StringIO
  1. >>> from io import StringIO;
  2. >>> f = StringIO();
  3. >>> f.write("你好");
  4. 2
  5. >>> f.write("浏阳河啊");
  6. 4
  7. >>> print(f.getvalue());
  8. 你好浏阳河啊
  9. >>>
  10. >>> f.write("\n浪页吗浪那个浪");
  11. 8
  12. >>> f.write("\n啊");
  13. 2
  14. >>> print(f.getvalue());
  15. 你好浏阳河啊
  16. 浪页吗浪那个浪
  17. >>> def readStringIO():
  18. ...     f = StringIO("1\n\t222\n33333");
  19. ...     while True:
  20. ...         s = f.readline();
  21. ...         if s == "":
  22. ...             break;
  23. ...         print(s.strip());
  24. ...
  25. >>> readStringIO();
  26. 1
  27. 222
  28. 33333
  29. >>>
这个是内存文本读写
这个是类似于Xml流读取,有记忆位置。

②BytesIO
  1. >>> from io import BytesIO;
  2. >>> f = BytesIO();
  3. >>> f.write("啊".encode("utf-8"));
  4. 3
  5. >>> print(f.getvalue());
  6. b'\xe5\x95\x8a'
  7. >>>
  8. >>> from io import BytesIO;
  9. >>> f = BytesIO(b"xe5\x95\x8a");
  10. >>> f.read();
  11. b'xe5\x95\x8a'
  12. >>>

3)文件目录操作

①系统名称和环境变量
  1. >>> import os;
  2. >>> os.name;
  3. 'posix'
  4. >>> os.uname();
  5. 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')
  6. >>> os.environ;# 环境变量
  7. 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'})
  8. >>> os.environ.get("PATH");
  9. '/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'
  10. >>> os.environ.get("x","default");
  11. 'default'
  12. >>>

②文件和目录操作
  1. >>> os.path.abspath(".");
  2. '/home/senrsl/test/python3'
  3. >>> os.path.join("/home/senrsl/test/python3","newDir");
  4. '/home/senrsl/test/python3/newDir'
  5. >>> os.mkdir("/home/senrsl/test/python3/newDir");
  6. >>> os.rmdir("/home/senrsl/test/python3/newDir");
  7. ('/home/senrsl/test/python3', 'newDir')
  8. >>> os.path.splitext("/home/senrsl/test/python3/newDir/xxx.txt");
  9. ('/home/senrsl/test/python3/newDir/xxx', '.txt')
  10. >>> os.rename("tmp","tmp01");
  11. >>> os.remove("tmp01");
  12. >>> [x for x in os.listdir(".")if os.path.isdir(x)]
  13. ['__pycache__', 'doctest', 'unittest', 'newTxt01']
  14. >>> [x for x in os.listdir(".")if os.path.isfile(x) and os.path.splitext(x)[1]==".py"]
  15. ['helloWorld01.py', 'helloWorld.py']
  16. >>>


4)序列化
把变量从内存中变成可存储或传输的过程叫序列化。
picking,serialization,marshaling,flattening....

把变量内容从序列化的对象重新读到内存里称之为反序列化,叫unpicking.

①pickle模块用来序列化。

  1. >>> import pickle;
  2. >>> d = dict(name="aaa",age=10);
  3. >>> pickle.dumps(d);
  4. b'\x80\x03}q\x00(X\x03\x00\x00\x00ageq\x01K\nX\x04\x00\x00\x00nameq\x02X\x03\x00\x00\x00aaaq\x03u.'
  5. >>> f = open("dump.txt","wb");
  6. >>> pickle.dump(d,f);
  7. >>> f.close();
  8. >>>
  9. >>> f = open("dump.txt","rb");
  10. >>> d = pickle.load(f);
  11. >>> f.close();
  12. >>> d
  13. {'age': 10, 'name': 'aaa'}
  14. >>>
序列化后保存到文件,然后读取后反序列化解析。

②使用json模块序列化
  1. >>> import json;
  2. >>> d = dict(name="aa",age=10);
  3. >>> json.dumps(d);
  4. '{"age": 10, "name": "aa"}'
  5. >>>
  6. >>> json_str = json.dumps(d);
  7. >>> json.loads(json_str);
  8. {'age': 10, 'name': 'aa'}
  9. >>>
json和python数据类型对应关系:
  1. JSON类型    Python类型
  2. {}                    dict
  3. []                    list
  4. "string"            str
  5. 1234.56            int或float
  6. true/false           True/False
  7. null                   None
官方图对应如下:


☂③类序列化为json
序列化:
  1. >>> import json;
  2. >>>
  3. >>> class Student(object):
  4. ...     def __init__(self,name,age):
  5. ...         self.name = name;
  6. ...         self.age = age;
  7. ...
  8. >>> s = Student("bbb",10);
  9. >>> def student2dict(std):
  10. ...     return{
  11. ...         "name":std.name,
  12. ...         "age":std.age
  13. ...     }
  14. ...
  15. >>> print(json.dumps(s,default=student2dict));
  16. {"name": "bbb", "age": 10}
  17. >>>
  18. >>> print(json,dumps(s,default=lambda obj:obj.__dict__));
  19. Traceback (most recent call last):
  20.   File "<stdin>", line 1, in <module>
  21. NameError: name 'dumps' is not defined
  22. >>>
反序列化:
  1. >>> def dict2student(d):
  2. ...     return Student(d["name"],d["age"]);
  3. ...
  4. >>> json_str = '{"name":"cccc","age":10}';
  5. >>> print(json.loads(json_str,object_hook=dict2student));
  6. <__main__.Student object at 0x7f3d23e94ac8>
  7. >>>


11,进程和线程

1)多进程
①创建一个子进程
使用fork()创建子进程
这种方法不适用win系统
  1. senrsl@senrsl-T540p:~/test/python3$ mkdir process
  2. senrsl@senrsl-T540p:~/test/python3$ touch process/test_fock.py
  3. senrsl@senrsl-T540p:~/test/python3$ vi process/test_fock.py
  4. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_fock.py
  5. Process 27345 start....
  6. 父线程27345将创建一个子线程27346
  7. 子线程是27346 and 父线程是27345
  8. senrsl@senrsl-T540p:~/test/python3$ cat process/test_fock.py
  9. import os;
  10. print("Process %s start...." % os.getpid());
  11. pid = os.fork();
  12. if pid == 0:
  13.     print("子线程是%s and 父线程是%s" % (os.getpid(),os.getppid()));
  14. else:
  15.     print("父线程%s将创建一个子线程%s" % (os.getpid(),pid));
  16. senrsl@senrsl-T540p:~/test/python3$
fork()函数调用一次返回两次。调用时,操作系统自动把当前进程(父进程)复制一份(子进程),然后分别在这俩进程里返回。

②使用multiprocessing模块创建子进程
  1. senrsl@senrsl-T540p:~/test/python3$ touch process/test_multiprocessing.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi process/test_multiprocessing.py
  3. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_multiprocessing.py
  4. 父线程4096
  5. 子线程启动
  6. 运行子线程test 标号为4097
  7. 子线程结束
  8. senrsl@senrsl-T540p:~/test/python3$ cat process/test_multiprocessing.py
  9. #!/usr/bin/env python3
  10. # -*- coding:utf-8 -*-
  11. from multiprocessing import Process;
  12. import os;
  13. def run_proc(name):
  14.     print("运行子线程%s 标号为%s" % (name,os.getpid()));
  15. if __name__ == "__main__":
  16.     print("父线程%s" % os.getpid());
  17.     p = Process(target=run_proc,args=("test",));
  18.     print("子线程启动");
  19.     p.start();
  20.     p.join();
  21.     print("子线程结束");
  22. senrsl@senrsl-T540p:~/test/python3$
千万不要让文件名跟系统内置的重复,之前起名叫multiprocessing.py,一直ImportError: cannot import name 'Process',然后改名并把之前那个删了就好了。。。。

③进程池pool
  1. senrsl@senrsl-T540p:~/test/python3$ touch process/test_pool.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi process/test_pool.py
  3. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_pool.py
  4. 父进程8309
  5. 等待执行完成
  6. 运行任务0 8310
  7. 运行任务1 8311
  8. 运行任务2 8312
  9. 运行任务3 8313
  10. 运行任务4 8314
  11. 运行任务5 8315
  12. 运行任务6 8316
  13. 运行任务7 8317
  14. 任务2运行0.28秒
  15. 运行任务8 8312
  16. 任务5运行0.66秒
  17. 任务6运行0.90秒
  18. 任务8运行0.95秒
  19. 任务3运行1.77秒
  20. 任务4运行1.89秒
  21. 任务0运行1.96秒
  22. 任务1运行2.69秒
  23. 任务7运行2.79秒
  24. 执行结束
  25. senrsl@senrsl-T540p:~/test/python3$ cat process/test_pool.py
  26. #!/usr/bin/env python3
  27. # -*- coding:utf-8 -*-
  28. from multiprocessing import Pool;
  29. import os,time,random;
  30. def long_time_task(name):
  31.     print("运行任务%s %s" % (name,os.getpid()));
  32.     start = time.time();
  33.     time.sleep(random.random() * 3);
  34.     end = time.time();
  35.     print("任务%s运行%0.2f秒" % (name,(end-start)));
  36. if __name__ == "__main__":
  37.     print("父进程%s" % os.getpid());
  38.     p = Pool(8);
  39.     for i in range(9):
  40.         p.apply_async(long_time_task,args=(i,));
  41.     print("等待执行完成");
  42.     p.close();
  43.     p.join();
  44.     print("执行结束");
  45. senrsl@senrsl-T540p:~/test/python3$
Pool的默认大小是CPU核数,上面设置的8,意为最多同时可以跑8个进程。

④子进程
subprocess模块的用法
  1. >>> import subprocess;
  2. >>> print("$ nslookup www.python.org");
  3. $ nslookup www.python.org
  4. >>> r = subprocess.call(["nslookup","www.python.org"]);
  5. Server:        127.0.1.1
  6. Address:    127.0.1.1#53
  7. Non-authoritative answer:
  8. www.python.org    canonical name = python.map.fastly.net.
  9. python.map.fastly.net    canonical name = prod.python.map.fastlylb.net.
  10. Name:    prod.python.map.fastlylb.net
  11. Address: 151.101.88.223
  12. >>> print("exit",r);
  13. exit 0
  14. >>>
手动输入:
  1. senrsl@senrsl-T540p:~/test/python3$ touch process/test_subprocess.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi process/test_subprocess.py
  3. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_subprocess.py
  4. $ nslookup
  5. Server:        127.0.1.1
  6. Address:    127.0.1.1#53
  7. Non-authoritative answer:
  8. python.org    mail exchanger = 50 mail.python.org.
  9. Authoritative answers can be found from:
  10. Exit code: 0
  11. senrsl@senrsl-T540p:~/test/python3$ cat process/test_subprocess.py
  12. #!/usr/bin/env python3
  13. # -*- coding:utf-8 -*-
  14. import subprocess;
  15. print("$ nslookup");
  16. p = subprocess.Popen(["nslookup"],stdin=subprocess.PIPE,stdout=subprocess.PIPE,stderr=subprocess.PIPE);
  17. output,err = p.communicate(b"set q=mx\npython.org\nexit\n");
  18. print(output.decode("utf-8"));
  19. print("Exit code:",p.returncode);
  20. senrsl@senrsl-T540p:~/test/python3$

⑤进程间通信
以Queue为例,实现一个读一个写:
  1. senrsl@senrsl-T540p:~/test/python3$ touch process/test_queue.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi process/test_queue.py
  3. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_queue.py
  4. 写进程:16811
  5. put a to queue....
  6. 读进程:16812
  7. get a from queue....
  8. put b to queue....
  9. get b from queue....
  10. put C to queue....
  11. get C from queue....
  12. senrsl@senrsl-T540p:~/test/python3$ cat process/test_queue.py
  13. #!/usr/bin/env python3
  14. # -*- coding:utf-8 -*-
  15. from multiprocessing import Process,Queue;
  16. import os,time,random;
  17. def write(q):
  18.     print("写进程:%s" % os.getpid());
  19.     for value in ["a","b","C"]:
  20.         print("put %s to queue...." % value);
  21.         q.put(value);
  22.         time.sleep(random.random());
  23. def read(q):
  24.     print("读进程:%s" % os.getpid());
  25.     while True:
  26.         value = q.get(True);
  27.         print("get %s from queue...." % value);
  28. if __name__ == "__main__":
  29.     q = Queue();
  30.     pw = Process(target=write,args=(q,));
  31.     pr = Process(target=read,args=(q,));
  32.     pw.start();
  33.     pr.start();
  34.     pw.join();
  35.     pr.terminate();
  36. senrsl@senrsl-T540p:~/test/python3$
进程间通信可以使用Queue,Pipes等实现。


2)多线程
多任务可以由多进程完成,也可以由一个进程内多线程完成。
python标准库提供两个模块,_thread和threading,后者对前者进行了封装。

①使用threading启动线程
  1. senrsl@senrsl-T540p:~/test/python3$ touch process/test_threading.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi process/test_threading.py
  3. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_threading.py
  4. 线程MainThread运行中。。。
  5. 线程LoopThread运行中。。。。
  6. 线程LoopThread >>>>>> 1
  7. 线程LoopThread >>>>>> 2
  8. 线程LoopThread >>>>>> 3
  9. 线程LoopThread >>>>>> 4
  10. 线程LoopThread >>>>>> 5
  11. 线程LoopThread结束
  12. 线程MainThread结束
  13. senrsl@senrsl-T540p:~/test/python3$ cat process/test_threading.py
  14. #!/usr/bin/env python3
  15. # -*- coding:utf-8 -*-
  16. import time,threading;
  17. def loop():
  18.     print("线程%s运行中。。。。" % threading.current_thread().name);
  19.     n = 0;
  20.     while n <5:
  21.         n = n+ 1;
  22.         print("线程%s >>>>>> %s" % (threading.current_thread().name,n));
  23.         time.sleep(1);
  24.     print("线程%s结束" % threading.current_thread().name);
  25. print("线程%s运行中。。。" % threading.current_thread().name);
  26. t = threading.Thread(target=loop,name="LoopThread");
  27. t.start();
  28. t.join();
  29. print("线程%s结束" %  threading.current_thread().name);
  30. senrsl@senrsl-T540p:~/test/python3$

②线程锁
不加锁,变量结果随机化:
  1. senrsl@senrsl-T540p:~/test/python3$ touch process/test_lock.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi process/test_lock.py
  3. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
  4. 执行完成,余额: 5
  5. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
  6. 执行完成,余额: -16
  7. senrsl@senrsl-T540p:~/test/python3$ cat process/test_lock.py
  8. #!/usr/bin/env python3
  9. # -*- coding:utf-8 -*-
  10. import time,threading;
  11. balance = 0;
  12. def change_it(n):
  13.     global balance;
  14.     balance = balance +n;
  15.     balance = balance -n;
  16. def run_thread(n):
  17.     for i in range(1000000):
  18.         change_it(n);
  19. t1 = threading.Thread(target=run_thread,args=(5,));
  20. t2 = threading.Thread(target=run_thread,args=(8,));
  21. t1.start();
  22. t2.start();
  23. t1.join();
  24. t2.join();
  25. print("执行完成,余额:",balance);
  26. senrsl@senrsl-T540p:~/test/python3$
加锁:
  1. senrsl@senrsl-T540p:~/test/python3$ vi process/test_lock.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
  3. 执行完成,余额: 0
  4. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
  5. 执行完成,余额: 0
  6. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_lock.py
  7. 执行完成,余额: 0
  8. senrsl@senrsl-T540p:~/test/python3$ cat process/test_lock.py
  9. #!/usr/bin/env python3
  10. # -*- coding:utf-8 -*-
  11. import time,threading;
  12. balance = 0;
  13. lock = threading.Lock();
  14. def change_it(n):
  15.     global balance;
  16.     balance = balance +n;
  17.     balance = balance -n;
  18. def run_thread(n):
  19.     for i in range(1000000):
  20.         lock.acquire(); # 持有锁:
  21.         try:
  22.             change_it(n);
  23.         finally:
  24.             lock.release();#释放锁
  25. t1 = threading.Thread(target=run_thread,args=(5,));
  26. t2 = threading.Thread(target=run_thread,args=(8,));
  27. t1.start();
  28. t2.start();
  29. t1.join();
  30. t2.join();
  31. print("执行完成,余额:",balance);
  32. senrsl@senrsl-T540p:~/test/python3$
加锁后,执行速度明显变慢了。

③GIL锁
历史遗留,GIL锁,Global Interpreter Lock,任何python线程执行前,必须先获取GIL锁,每执行100条字节自动释放。
所以,多线程并非多核任务,要实现多核任务可以用多进程实现,每个进程都有自己独立的GIL锁。


3)ThreadLocal
ThreadLocal解决参数在一个线程中各个函数之间互相传递的问题
  1. senrsl@senrsl-T540p:~/test/python3$ touch process/test_thread_local.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi process/test_thread_local.py
  3. senrsl@senrsl-T540p:~/test/python3$ python3 process/test_thread_local.py
  4. 你好,i小A 线程Thread-0001
  5. 你好,小B 线程Thread-B
  6. senrsl@senrsl-T540p:~/test/python3$ cat process/test_thread_local.py
  7. #!/usr/bin/env python3
  8. # -*- coding:utf-8 -*-
  9. import threading;
  10. local_school = threading.local();
  11. def process_student():
  12.     std = local_school.student;
  13.     print("你好,%s 线程%s" % (std,threading.current_thread().name));
  14. def process_thread(name):
  15.     local_school.student = name;
  16.     process_student();
  17. t1 = threading.Thread(target=process_thread,args = ("i小A",),name="Thread-0001");
  18. t2 = threading.Thread(target=process_thread,args=("小B",),name="Thread-B");
  19. t1.start();
  20. t2.start();
  21. t1.join();
  22. t2.join();
  23. senrsl@senrsl-T540p:~/test/python3$
全局定义,线程独立。

4)分布式进程
Process比Thread稳定
  1. senrsl@senrsl-T540p:~/test/python3$ touch process/process_server.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi process/process_server.py
  3. senrsl@senrsl-T540p:~/test/python3$ vi process/process_worker.py
  4. senrsl@senrsl-T540p:~/test/python3$ vi process/process_worker.py
然后开两个终端,分别启动这俩
master端:
  1. senrsl@senrsl-T540p:~$ cd test/python3/
  2. senrsl@senrsl-T540p:~/test/python3$ python3 process/process_server.py
  3. 添加任务6055....
  4. 添加任务6920....
  5. 添加任务9338....
  6. 添加任务9157....
  7. 添加任务5901....
  8. 添加任务2697....
  9. 添加任务6492....
  10. 添加任务889....
  11. 添加任务8875....
  12. 添加任务4819....
  13. 获取数据:
  14. 返回6055 * 6055 = 36663025!
  15. 返回6920 * 6920 = 47886400!
  16. 返回9338 * 9338 = 87198244!
  17. 返回9157 * 9157 = 83850649!
  18. 返回5901 * 5901 = 34821801!
  19. 返回2697 * 2697 = 7273809!
  20. 返回6492 * 6492 = 42146064!
  21. 返回889 * 889 = 790321!
  22. 返回8875 * 8875 = 78765625!
  23. 返回4819 * 4819 = 23222761!
  24. 退出
  25. senrsl@senrsl-T540p:~/test/python3$
worker端:
  1. senrsl@senrsl-T540p:~/test/python3$ python3 process/process_server.py
  2. 添加任务6055....
  3. 添加任务6920....
  4. 添加任务9338....
  5. 添加任务9157....
  6. 添加任务5901....
  7. 添加任务2697....
  8. 添加任务6492....
  9. 添加任务889....
  10. 添加任务8875....
  11. 添加任务4819....
  12. 获取数据:
  13. 返回6055 * 6055 = 36663025!
  14. 返回6920 * 6920 = 47886400!
  15. 返回9338 * 9338 = 87198244!
  16. 返回9157 * 9157 = 83850649!
  17. 返回5901 * 5901 = 34821801!
  18. 返回2697 * 2697 = 7273809!
  19. 返回6492 * 6492 = 42146064!
  20. 返回889 * 889 = 790321!
  21. 返回8875 * 8875 = 78765625!
  22. 返回4819 * 4819 = 23222761!
  23. 退出
  24. senrsl@senrsl-T540p:~/test/python3$
图示:



源码:
  1. senrsl@senrsl-T540p:~/test/python3$ cat process/process_server.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. import random,time,queue;
  5. from multiprocessing.managers import BaseManager
  6. #发送任务的队列
  7. task_queue = queue.Queue();
  8. #接收任务队列
  9. result_queue = queue.Queue();
  10. class QueueManager (BaseManager):
  11.     pass;
  12. #把两个Queue都注册到网络上,callable参数关联了Queue对象
  13. QueueManager.register("get_task_queue",callable=lambda:task_queue);
  14. QueueManager.register("get_result_queue",callable=lambda:result_queue);
  15. #绑定端口5000,设置验证码abc
  16. manager = QueueManager(address=("",5000),authkey=b"abc");
  17. #启动Queue
  18. manager.start();
  19. #获得通过网络访问的Queue对象
  20. task = manager.get_task_queue();
  21. result = manager.get_result_queue();
  22. #添加任务
  23. for i in range(10):
  24.     n = random.randint(0,10000);
  25.     print("添加任务%d...." % n);
  26.     task.put(n);
  27. #从result队列读取结果
  28. print("获取数据:");
  29. for i in range(10):
  30.     r = result.get(timeout=10);
  31.     print("返回%s" % r);
  32. #关闭
  33. manager.shutdown();
  34. print("退出");
  35. senrsl@senrsl-T540p:~/test/python3$ cat process/process_worker.py
  36. #!/usr/bin/env python3
  37. # -*- coding:utf-8 -*-
  38. import time,sys,queue;
  39. from multiprocessing.managers import BaseManager;
  40. class QueueManager(BaseManager):
  41.     pass;
  42. QueueManager.register("get_task_queue");
  43. QueueManager.register("get_result_queue");
  44. server_addr = "127.0.0.1";
  45. print("连接到服务%s。。。。" % server_addr);
  46. m = QueueManager(address=(server_addr,5000),authkey=b"abc");
  47. m.connect();
  48. task = m.get_task_queue();
  49. result = m.get_result_queue();
  50. for i in range(10):
  51.     try:
  52.         n = task.get(timeout=1);
  53.         print("运行任务%d * %d...." % (n,n));
  54.         r = "%d * %d = %d!" % (n,n,n*n);
  55.         time.sleep(1);
  56.         result.put(r);
  57.     except Queue.Empty:
  58.         print("空异常");
  59. print("workder exit!");
  60. senrsl@senrsl-T540p:~/test/python3$
master端等待异常的时候没有去关闭,所以下次再启动会端口占用。所以加try-catch很重要。


12,正则表达式
正则,又见正则

基本使用方法:
  1. >>> import re;
  2. >>> re.split(r"[\s\,]","a,b,c d");
  3. ['a', 'b', 'c', 'd']
  4. >>> re.split(r"\s\,\;+","a,b;;c d");
  5. ['a,b;;c d']
  6. >>> re.split(r"[\s\,\;]+","a,b;;c d");
  7. ['a', 'b', 'c', 'd']
  8. >>>

一次编译,多次使用:
  1. >>> import re;
  2. >>> re_telphone = re.compile(r"^(\d{3})-(\d{3,8})$");#编译
  3. >>> re_telphone.match("010-12345").groups();#使用
  4. ('010', '12345')
  5. >>> re_telphone.match("010-10086").groups();
  6. ('010', '10086')
  7. >>>
此处入库

13,常用内建模块
batteries included


1)datetime
处理日期和时间
  1. senrsl@senrsl-T540p:~/test/python3$ vi module/test_datetime.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 module/test_datetime.py
  3. 2016-07-01 15:20:45.316538
  4. <class 'datetime.datetime'>
  5. datetime为2016-07-01 11:12:00
  6. timestamp为:1467342720.0
  7. 转换timestamp为datetime,使用本地时区:2016-07-01 11:12:00
  8. 转换timestamp为datetime,使用utc标准时区:2016-07-01 03:12:00
  9. str转换为datetime: 2016-07-01 11:26:11
  10. datetime转换为str: Fri,Jul 01 15:20
  11. 2016-07-01 15:20:45.316538
  12. 2016-07-02 01:20:45.316538
  13. 2016-06-30 15:20:45.316538
  14. 2016-07-04 03:20:45.316538
  15. UTC时间: 2016-07-01 07:20:45.324733+00:00
  16. 北京时间: 2016-07-01 15:20:45.324733+08:00
  17. 东京时间 2016-07-01 16:20:45.324733+09:00
  18. 北京时间转东京时间 2016-07-01 16:20:45.324733+09:00
  19. 强制设置+8时区 2016-07-01 15:20:45.316538+08:00
  20. senrsl@senrsl-T540p:~/test/python3$ cat module/test_datetime.py
  21. #!/usr/bin/env python3
  22. # -*- coding:utf-8 -*-
  23. from datetime import datetime,timedelta,timezone;
  24. #获取当前日期和时间
  25. now = datetime.now();
  26. print(now);
  27. print(type(now));
  28. #获取指定日期和时间
  29. dt = datetime(2016,7,1,11,12);
  30. print("datetime为%s" % dt);
  31. #转换为timestamp
  32. #python小数位表示毫秒,算法为java/1000=python
  33. t = dt.timestamp();
  34. print("timestamp为:%s" % t);
  35. #timestamp转换为datetime
  36. print("转换timestamp为datetime,使用本地时区:%s" % datetime.fromtimestamp(t));
  37. print("转换timestamp为datetime,使用utc标准时区:%s" % datetime.utcfromtimestamp(t));
  38. #str转换为datetime
  39. cday = datetime.strptime("2016-7-1 11:26:11","%Y-%m-%d %H:%M:%S");
  40. print("str转换为datetime:",cday);
  41. #datetime转换为str
  42. print("datetime转换为str:",now.strftime("%a,%b %d %H:%M"));
  43. #datetime加减
  44. print(now);
  45. print(now + timedelta(hours = 10));
  46. print(now - timedelta(days=1));
  47. print(now + timedelta(days=2,hours=12));
  48. #拿到UTC时间,转换时区
  49. utc_dt = datetime.utcnow().replace(tzinfo=timezone.utc);
  50. print("UTC时间:",utc_dt);
  51. bj_dt = utc_dt.astimezone(timezone(timedelta(hours=8)));
  52. print("北京时间:",bj_dt);
  53. tokyo_dt = utc_dt.astimezone(timezone(timedelta(hours=9)));
  54. print("东京时间",tokyo_dt);
  55. #北京时间转东京时间
  56. tokyo_dt2 = bj_dt.astimezone(timezone(timedelta(hours=9)));
  57. print("北京时间转东京时间",tokyo_dt2);
  58. #默认datetime时区属性为None,强制设置时区属性
  59. tz_utc_8 = timezone(timedelta(hours=8));#创建+8时区
  60. set8_dt = now.replace(tzinfo=tz_utc_8);
  61. print("强制设置+8时区",set8_dt);
  62. senrsl@senrsl-T540p:~/test/python3$

2)collections
提供集合类

①namedtuple
带名的tuple
  1. >>> from collections import namedtuple;
  2. >>> Point = namedtuple("Point",["x","y"]);
  3. >>> p = Point(1,2);
  4. >>> p.x
  5. 1
  6. >>> p.y
  7. 2
  8. >>> isinstance(p,Point);
  9. True
  10. >>> isinstance(p,tuple);
  11. True
  12. >>>

②deque
两头操作的list
  1. >>> from collections import deque;
  2. >>> q = deque(["a","b","c"]);
  3. >>> q.append("d");
  4. >>> q.appendleft("e");
  5. >>> q
  6. deque(['e', 'a', 'b', 'c', 'd'])
  7. >>> q.popleft();
  8. 'e'
  9. >>> q
  10. deque(['a', 'b', 'c', 'd'])
  11. >>>

③defaultdict
当dict的key不存在时返回默认值
  1. >>> from collections import defaultdict;
  2. >>> dd = defaultdict(lambda:"N/A");
  3. >>> dd["key1"] = "abc";
  4. >>> dd["key1"]
  5. 'abc'
  6. >>> dd["key2"]
  7. 'N/A'
  8. >>>
④OrderedDict
有序的dict
  1. >>> from collections import OrderedDict;
  2. >>> d = dict([("a",1),("b",2),("c",3)]);
  3. >>> d
  4. {'c': 3, 'b': 2, 'a': 1}
  5. >>> od = OrderedDict([("a",1),("b",2),("c",3)]);
  6. >>> od
  7. OrderedDict([('a', 1), ('b', 2), ('c', 3)])
  8. >>>

⑤Counter
一个简单的计数器
  1. >>> from collections import Counter;
  2. >>> c = Counter();
  3. >>> for ch in "fdsafsdafsafsdafjdsalkfsadjffewgfewfa":
  4. ...     c[ch] = c[ch]+1;
  5. ...
  6. >>> c
  7. Counter({'f': 10, 'a': 7, 's': 6, 'd': 5, 'w': 2, 'j': 2, 'e': 2, 'g': 1, 'l': 1, 'k': 1})
  8. >>>

3)base64
用64个字符表示二进制数据的方法
准备64个字符的数组,然后对二进制每3个字节(Byte)一组,3个字节*8位(bit)=24位.
24位除以4(索引)等于6位一组。
4索引查64字符数组,取值为编码后字符。
如果3字节分组时有余,用\x00补足,再在编码后末尾加相应数的=表示补了多少字节。

  1. >>> import base64;
  2. >>> base64.b64encode(b'a');
  3. b'YQ=='
  4. >>> base64.b64decode(b"b'YQ=='");
  5. b'm\x84'
  6. >>> base64.b64decode(b"YQ==");
  7. b'a'
  8. >>>
  9. >>> base64.b64encode(b"i\xb7\x1d\xfb\xef\xff");
  10. b'abcd++//'
  11. >>> base64.urlsafe_b64encode(b"i\xb7\x1d\xfb\xef\xff");
  12. b'abcd--__'
  13. >>> base64.urlsafe_b64decode(b'abcd--__');
  14. b'i\xb7\x1d\xfb\xef\xff'
  15. >>>
因为base64永远是4的倍数,所以传输中可以把后面补的=去掉,接收方收到再补成4的倍数解析。


4)struct
用于处理bytes和其他二进制数据类型转换
  1. >>> import struct;
  2. >>> struct.pack(">I",10240099);
  3. b'\x00\x9c@c'
  4. >>> struct.unpack(">I",b'\x00\x9c@c');
  5. >>> struct.unpack(">IH",b'\xf0\xf0\xf0\xf0\x80\x80');
  6. (4042322160, 32896)
  7. >>>
第一个参数是处理指令,>表示字节顺序为big-endian,即网络序,I表示4字节无符号整数,H表示2字节无符号整数。
第二个参数要跟第一个参数指示的长度一致。

处理指令对应表:

地址在https://docs.python.org/3/library/struct.html#format-characters

5)hashlib
提供常见的摘要算法,如MD5,SHA1等
  1. >>> import hashlib;
  2. >>> md5 = hashlib.md5();
  3. >>> md5.update("fuck".encode("utf-8"));
  4. >>> print(md5.hexdigest());
  5. 99754106633f94d350db34d548d6091a
  6. >>> md501 = hashlib.md5();
  7. >>> md501.update("fu".encode("utf-8"));
  8. >>> md501.update("ck".encode("utf-8"));
  9. >>> print(md501.hexdigest());
  10. 99754106633f94d350db34d548d6091a
  11. >>>
  12. >>> sha1 = hashlib.sha1();
  13. >>> sha1.update("fuck".encode("utf-8"));
  14. >>> print(sha1.hexdigest());
  15. 38d0f91a99c57d189416439ce377ccdcd92639d0
  16. >>>
MD5生成固定128位字节,通常用一个32位的16进制字符串表示;
SHA1生成160位字节,通常用一个40位的16进制字符串表示;

通过原始口令,加一个复杂字符串来计算MD5,俗称:加盐。


6)itertools
操作迭代对象。

①无限迭代
  1. >>> import itertools;
  2. >>> natuals = itertools.count(1);
  3. >>> for n in natuals:
  4. ...     print(n);
  5. ...     if n >10:
  6. ...         break;
  7. ...
  8. 1
  9. 2
  10. 3
  11. 4
  12. 5
  13. 6
  14. 7
  15. 8
  16. 9
  17. 10
  18. 11
  19. >>> cs = itertoos.cycle("ABCD");
  20. Traceback (most recent call last):
  21.   File "<stdin>", line 1, in <module>
  22. NameError: name 'itertoos' is not defined
  23. >>> cs = itertools.cycle("ABCD");
  24. >>> i = 1;
  25. >>> for c in cs:
  26. ...     print(c);
  27. ...     i = i +1;
  28. ...     if i > 10:
  29. ...         break;
  30. ...
  31. A
  32. B
  33. C
  34. D
  35. A
  36. B
  37. C
  38. D
  39. A
  40. B
  41. >>> ns = itertools.repeat("A",10);
  42. >>> for n in ns:
  43. ...     print(n);
  44. ...
  45. A
  46. A
  47. A
  48. A
  49. A
  50. A
  51. A
  52. A
  53. A
  54. A
  55. >>> natuals = itertoos.count(1);
  56. Traceback (most recent call last):
  57.   File "<stdin>", line 1, in <module>
  58. NameError: name 'itertoos' is not defined
  59. >>> natuals = itertools.count(1);
  60. >>> ns = itertools.takewhile(lambda x:x<10,natuals);
  61. >>> list(ns);
  62. [1, 2, 3, 4, 5, 6, 7, 8, 9]
  63. >>>

②chain()
迭代对象串联
  1. >>> for c in itertools.chain("ABC","XYZ"):
  2. ...     print(c);
  3. ...
  4. A
  5. B
  6. C
  7. X
  8. Y
  9. Z
  10. >>>

③groupby()
相邻的重复元素放一块
  1. >>> for key,group in itertools.groupby("AABBCCCDDDDDDDAAAAA"):
  2. ...     print(key,list(group));
  3. ...
  4. A ['A', 'A']
  5. B ['B', 'B']
  6. C ['C', 'C', 'C']
  7. D ['D', 'D', 'D', 'D', 'D', 'D', 'D']
  8. A ['A', 'A', 'A', 'A', 'A']
  9. >>> for key,group in itertools.groupby("AABBCcCDdddddDDDDDaAAAA",lambda c:c.upper()):
  10. ...     print(key,list(group));...
  11. A ['A', 'A']
  12. B ['B', 'B']
  13. C ['C', 'c', 'C']
  14. D ['D', 'd', 'd', 'd', 'd', 'd', 'D', 'D', 'D', 'D', 'D']
  15. A ['a', 'A', 'A', 'A', 'A']
  16. >>>

7)XML
DOM,SAX,没有PULL?
  1. senrsl@senrsl-T540p:~/test/python3$ vi module/test_sax.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 module/test_sax.py
  3. start_element:ol,attrs:{}
  4. char_data:
  5. char_data:   
  6. start_element:li,attrs:{}
  7. start_element:a,attrs:{'href': 'python'}
  8. char_data:python
  9. end_elements:a
  10. end_elements:li
  11. char_data:
  12. char_data:   
  13. start_element:li,attrs:{}
  14. start_element:a,attrs:{'href': 'ruby'}
  15. char_data:ruby
  16. end_elements:a
  17. end_elements:li
  18. char_data:
  19. end_elements:ol
  20. senrsl@senrsl-T540p:~/test/python3$ cat module/test_sax.py
  21. #!/usr/bin/env python3
  22. # -*- coding:utf-8 -*-
  23. from xml.parsers.expat import ParserCreate;
  24. class DefaultSaxHandler(object):
  25.     def start_element(self,name,attrs):
  26.         print("start_element:%s,attrs:%s" % (name,str(attrs)));
  27.     def end_element(self,name):
  28.         print("end_elements:%s" % name);
  29.     def char_data(self,text):
  30.         print("char_data:%s" % text);
  31. xml = r'''<?xml version="1.0"?>
  32. <ol>
  33.     <li><a href="python">python</a></li>
  34.     <li><a href="ruby">ruby</a></li>
  35. </ol>
  36. ''';
  37. handler = DefaultSaxHandler();
  38. parser = ParserCreate();
  39. parser.StartElementHandler =handler.start_element;
  40. parser.EndElementHandler = handler.end_element;
  41. parser.CharacterDataHandler = handler.char_data;
  42. parser.Parse(xml);
  43. senrsl@senrsl-T540p:~/test/python3$


8)HTMLParser
解析html
  1. senrsl@senrsl-T540p:~/test/python3$ touch module/test_html_parser.py
  2. senrsl@senrsl-T540p:~/test/python3$ vi module/test_html_parser.py
  3. senrsl@senrsl-T540p:~/test/python3$ python3 module/test_html_parser.py
  4. <html>
  5. <head>
  6. </head>
  7. <body>
  8. <!-- test html parser -->
  9.   
  10. <p>
  11. Some
  12. <a>
  13. html
  14. </a>
  15.  HTML
  16. &nbsp
  17. tutorial....
  18. <br/>
  19. End
  20. </p>
  21.  
  22. </html>
  23. senrsl@senrsl-T540p:~/test/python3$ cat module/test_html_parser.py
  24. #!/usr/bin/env python3
  25. # -*- coding:utf-8 -*-
  26. from html.parser import HTMLParser;
  27. from html.entities import name2codepoint;
  28. class MyHTMLParser(HTMLParser):
  29.     def handle_starttag(self,tag,attrs):
  30.         print("<%s>" % tag);
  31.     def handle_endtag(self,tag):
  32.         print("</%s>" % tag);
  33.     def handle_startendtag(self,tag,attrs):
  34.         print("<%s/>" % tag);
  35.     def handle_data(self,data):
  36.         print(data);
  37.     def handle_comment(self,data):
  38.         print("<!--%s-->" % data);
  39.     def handle_entityref(self,name):
  40.         print("&%s" % name);
  41.     def handle_charref(self,name):
  42.         print("&#%s" % name);
  43. parser = MyHTMLParser();
  44. parser.feed('''<html>
  45. <head></head>
  46. <body>
  47. <!-- test html parser -->
  48.    <p>Some <a href=\"#\">html</a> HTML &nbsp;tutorial....<br/>End</p>
  49. </html>''');
  50. senrsl@senrsl-T540p:~/test/python3$


9)urllib
用于URL操作。
①get请求
  1. senrsl@senrsl-T540p:~/test/python3$ vi module/test_urllib_get.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 module/test_urllib_get.py
  3. 状态: 200 OK
  4. Server:nginx
  5. Content-Type:text/html
  6. Last-Modified:Mon, 27 Jun 2016 05:11:22 GMT
  7. ETag:"5770b57a-18c4"
  8. X-Clacks-Overhead:GNU Terry Pratchett
  9. Strict-Transport-Security:max-age=315360000; includeSubDomains; preload
  10. Content-Length:6340
  11. Accept-Ranges:bytes
  12. Date:Fri, 01 Jul 2016 09:42:58 GMT
  13. Via:1.1 varnish
  14. Age:264375
  15. Connection:close
  16. X-Served-By:cache-itm7426-ITM
  17. X-Cache:HIT
  18. X-Cache-Hits:1
  19. 数据: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  20.   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  21. <html xmlns="http://www.w3.org/1999/xhtml">
  22.   <head>
  23.     <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
  24.    
  25.     <title>Copyright &mdash; Python 3.5.2 documentation</title>
  26.    
  27.     <link rel="stylesheet" href="_static/pydoctheme.css" type="text/css" />
  28.     <link rel="stylesheet" href="_static/pygments.css" type="text/css" />
  29.    
  30.     <script type="text/javascript">
  31.       var DOCUMENTATION_OPTIONS = {
  32.         URL_ROOT:    './',
  33.         VERSION:     '3.5.2',
  34.         COLLAPSE_INDEX: false,
  35.         FILE_SUFFIX: '.html',
  36.         HAS_SOURCE:  true
  37.       };
  38.     </script>
  39.     <script type="text/javascript" src="_static/jquery.js"></script>
  40.     <script type="text/javascript" src="_static/underscore.js"></script>
  41.     <script type="text/javascript" src="_static/doctools.js"></script>
  42.     <script type="text/javascript" src="_static/sidebar.js"></script>
  43.     <link rel="search" type="application/opensearchdescription+xml"
  44.           title="Search within Python 3.5.2 documentation"
  45.           href="_static/opensearch.xml"/>
  46.     <link rel="author" title="About these documents" href="about.html" />
  47.     <link rel="copyright" title="Copyright" href="#" />
  48.     <link rel="top" title="Python 3.5.2 documentation" href="contents.html" />
  49.     <link rel="next" title="History and License" href="license.html" />
  50.     <link rel="prev" title="Dealing with Bugs" href="bugs.html" />
  51.     <link rel="shortcut icon" type="image/png" href="_static/py.png" />
  52.     <script type="text/javascript" src="_static/copybutton.js"></script>
  53.     <script type="text/javascript" src="_static/version_switch.js"></script>
  54.    
  55.  
  56.   </head>
  57.   <body role="document"> 
  58.     <div class="related" role="navigation" aria-label="related navigation">
  59.       <h3>Navigation</h3>
  60.       <ul>
  61.         <li class="right" style="margin-right: 10px">
  62.           <a href="genindex.html" title="General Index"
  63.              accesskey="I">index</a></li>
  64.         <li class="right" >
  65.           <a href="py-modindex.html" title="Python Module Index"
  66.              >modules</a> |</li>
  67.         <li class="right" >
  68.           <a href="license.html" title="History and License"
  69.              accesskey="N">next</a> |</li>
  70.         <li class="right" >
  71.           <a href="bugs.html" title="Dealing with Bugs"
  72.              accesskey="P">previous</a> |</li>
  73.         <li><img src="_static/py.png" alt=""
  74.                  style="vertical-align: middle; margin-top: -1px"/></li>
  75.         <li><a href="https://www.python.org/">Python</a> &raquo;</li>
  76.         <li>
  77.           <span class="version_switcher_placeholder">3.5.2</span>
  78.           <a href="index.html">Documentation </a> &raquo;
  79.         </li>
  80.  
  81.       </ul>
  82.     </div>   
  83.     <div class="document">
  84.       <div class="documentwrapper">
  85.         <div class="bodywrapper">
  86.           <div class="body" role="main">
  87.            
  88.   <div class="section" id="copyright">
  89. <h1>Copyright<a class="headerlink" href="#copyright" title="Permalink to this headline">¶</a></h1>
  90. <p>Python and this documentation is:</p>
  91. <p>Copyright © 2001-2016 Python Software Foundation. All rights reserved.</p>
  92. <p>Copyright © 2000 BeOpen.com. All rights reserved.</p>
  93. <p>Copyright © 1995-2000 Corporation for National Research Initiatives. All rights
  94. reserved.</p>
  95. <p>Copyright © 1991-1995 Stichting Mathematisch Centrum. All rights reserved.</p>
  96. <hr class="docutils" />
  97. <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>
  98. </div>
  99.           </div>
  100.         </div>
  101.       </div>
  102.       <div class="sphinxsidebar" role="navigation" aria-label="main navigation">
  103.         <div class="sphinxsidebarwrapper">
  104.   <h4>Previous topic</h4>
  105.   <p class="topless"><a href="bugs.html"
  106.                         title="previous chapter">Dealing with Bugs</a></p>
  107.   <h4>Next topic</h4>
  108.   <p class="topless"><a href="license.html"
  109.                         title="next chapter">History and License</a></p>
  110. <h3>This Page</h3>
  111. <ul class="this-page-menu">
  112.   <li><a href="bugs.html">Report a Bug</a></li>
  113.   <li><a href="_sources/copyright.txt"
  114.          rel="nofollow">Show Source</a></li>
  115. </ul>
  116. <div id="searchbox" style="display: none" role="search">
  117.   <h3>Quick search</h3>
  118.     <form class="search" action="search.html" method="get">
  119.       <input type="text" name="q" />
  120.       <input type="submit" value="Go" />
  121.       <input type="hidden" name="check_keywords" value="yes" />
  122.       <input type="hidden" name="area" value="default" />
  123.     </form>
  124.     <p class="searchtip" style="font-size: 90%">
  125.     Enter search terms or a module, class or function name.
  126.     </p>
  127. </div>
  128. <script type="text/javascript">$('#searchbox').show(0);</script>
  129.         </div>
  130.       </div>
  131.       <div class="clearer"></div>
  132.     </div> 
  133.     <div class="related" role="navigation" aria-label="related navigation">
  134.       <h3>Navigation</h3>
  135.       <ul>
  136.         <li class="right" style="margin-right: 10px">
  137.           <a href="genindex.html" title="General Index"
  138.              >index</a></li>
  139.         <li class="right" >
  140.           <a href="py-modindex.html" title="Python Module Index"
  141.              >modules</a> |</li>
  142.         <li class="right" >
  143.           <a href="license.html" title="History and License"
  144.              >next</a> |</li>
  145.         <li class="right" >
  146.           <a href="bugs.html" title="Dealing with Bugs"
  147.              >previous</a> |</li>
  148.         <li><img src="_static/py.png" alt=""
  149.                  style="vertical-align: middle; margin-top: -1px"/></li>
  150.         <li><a href="https://www.python.org/">Python</a> &raquo;</li>
  151.         <li>
  152.           <span class="version_switcher_placeholder">3.5.2</span>
  153.           <a href="index.html">Documentation </a> &raquo;
  154.         </li>
  155.  
  156.       </ul>
  157.     </div> 
  158.     <div class="footer">
  159.     &copy; <a href="#">Copyright</a> 2001-2016, Python Software Foundation.
  160.     <br />
  161.     The Python Software Foundation is a non-profit corporation.
  162.     <a href="https://www.python.org/psf/donations/">Please donate.</a>
  163.     <br />
  164.     Last updated on Jun 27, 2016.
  165.     <a href="bugs.html">Found a bug</a>?
  166.     <br />
  167.     Created using <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.3.3.
  168.     </div>
  169.   </body>
  170. </html>
  171. senrsl@senrsl-T540p:~/test/python3$ cat module/test_urllib_get.py
  172. #!/usr/bin/env python3
  173. # -*- coding:utf-8 -*-
  174. from urllib import request;
  175. with request.urlopen("https://docs.python.org/3/copyright.html")as f:
  176.     data = f.read();
  177.     print("状态:",f.status,f.reason);
  178.     for k,v in f.getheaders():
  179.         print("%s:%s" % (k,v));
  180.     print("数据:",data.decode("utf-8"));
  181. senrsl@senrsl-T540p:~/test/python3$

②模拟浏览器发送get请求
效果:
  1. senrsl@senrsl-T540p:~/test/python3$ vi module/test_urllib_request.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 module/test_urllib_request.py
  3. 状态: 200 OK
  4. cache-control:no-cache, no-store, must-revalidate, pre-check=0, post-check=0
  5. connection:close
  6. content-language:en
  7. content-length:11056
  8. 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;
  9. content-type:text/html;charset=utf-8
  10. date:Fri, 01 Jul 2016 09:59:58 GMT
  11. expires:Tue, 31 Mar 1981 05:00:00 GMT
  12. last-modified:Fri, 01 Jul 2016 09:59:58 GMT
  13. pragma:no-cache
  14. server:tsa_b
  15. set-cookie:fm=0; Expires=Fri, 01 Jul 2016 09:59:48 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
  16. set-cookie:_mobile_sess=BAh7ByIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNoSGFzaHsABjoKQHVzZWR7ADoQX2NzcmZfdG9rZW4iJTE4NGRmMDk4NGM2NmY3YjM5ZDg5YzY4YzgzNTVhOWIz--f33fd98658e35723ca6e566960bf808296649d8c; Expires=Tue, 30 Aug 2016 09:59:58 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
  17. set-cookie:_twitter_sess=BAh7CCIKZmxhc2hJQzonQWN0aW9uQ29udHJvbGxlcjo6Rmxhc2g6OkZsYXNo%250ASGFzaHsABjoKQHVzZWR7ADoPY3JlYXRlZF9hdGwrCL2Q5qVVAToHaWQiJTRm%250ANWEzZjQ5MzliMjgzNjljZGRjZDkwNDRiYmQyODUx--a3a54fe95d78a2f274dda00e0166d75a057745e6; Path=/; Domain=.twitter.com; Secure; HTTPOnly
  18. set-cookie:mobile_metrics_token=146736719833153292; Expires=Sun, 01 Jul 2018 09:59:58 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
  19. set-cookie:zrca=5; Expires=Sun, 31 Jul 2016 09:59:58 GMT; Path=/; Domain=.twitter.com; Secure; HTTPOnly
  20. set-cookie:_mb_tk=184df0984c66f7b39d89c68c8355a9b3; Expires=Sun, 03 Jul 2016 09:59:58 GMT; Path=/; Secure; HTTPOnly
  21. set-cookie:guest_id=v1%3A146736719890570656; Domain=.twitter.com; Path=/; Expires=Sun, 01-Jul-2018 09:59:58 UTC
  22. strict-transport-security:max-age=631138519
  23. vary:Accept-Encoding
  24. x-connection-hash:c0746d4aab68be08e74a67582c8f3ea6
  25. x-content-type-options:nosniff
  26. x-frame-options:SAMEORIGIN
  27. x-response-time:13
  28. x-transaction:008cc52800e7ad00
  29. x-twitter-response-tags:BouncerCompliant
  30. x-xss-protection:1; mode=block
  31. 数据: <!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="{&quot;pwreset-iphone&quot;:true,&quot;android&quot;:true,&quot;email&quot;: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>
  32. senrsl@senrsl-T540p:~/test/python3$
代码:
  1. senrsl@senrsl-T540p:~/test/python3$ cat module/test_urllib_request.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. from urllib import request;
  5. req = request.Request("https://www.twitter.com/");
  6. 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');
  7. with request.urlopen(req) as f:
  8.     print("状态:",f.status,f.reason);
  9.     for k,v in f.getheaders():
  10.         print("%s:%s" % (k,v));
  11.     print("数据:",f.read().decode("utf-8"));
  12. senrsl@senrsl-T540p:~/test/python3$

③post请求
  1. senrsl@senrsl-T540p:~/test/python3$ vi module/test_urllib_post.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 module/test_urllib_post.py
  3. 登陆。。。。
  4. Email:a
  5. Password:b
  6. 状态: 200 OK
  7. Server : nginx/1.6.1
  8. Date : Fri, 01 Jul 2016 10:17:49 GMT
  9. Content-Type : text/html
  10. Transfer-Encoding : chunked
  11. Connection : close
  12. Vary : Accept-Encoding
  13. Cache-Control : no-cache, must-revalidate
  14. Expires : Sat, 26 Jul 1997 05:00:00 GMT
  15. Pragma : no-cache
  16. Access-Control-Allow-Origin : https://passport.weibo.cn
  17. Access-Control-Allow-Credentials : true
  18. DPOOL_HEADER : kotl85
  19. SINA-LB : aGEuNjIuZzEuYngubGIuc2luYW5vZGUuY29t
  20. SINA-TS : YTRjNGU0Y2UgMCAwIDAgNCA3NQo=
  21. 数据: {"retcode":50011002,"msg":"\u7528\u6237\u540d\u6216\u5bc6\u7801\u9519\u8bef","data":{"username":"a","errline":605}}
  22. senrsl@senrsl-T540p:~/test/python3$ cat module/test_urllib_post.py
  23. #!/usr/bin/env python3
  24. # -*- coding:utf-8 -*-
  25. from urllib import request,parse;
  26. print("登陆。。。。");
  27. email = input("Email:");
  28. password = input("Password:");
  29. login_data = parse.urlencode([
  30.     ("username",email),
  31.     ("password",password),
  32.     ("entry","mweibo"),
  33.     ("client_id",""),
  34.     ("savestate","1"),
  35.     ("ec",""),
  36.     ("pagerefer","://passport.weibo.cn/signin/welcome?entry=mweibo&r=http%3A%2F%2Fm.weibo.cn%2F")
  37. ]);
  38. req = request.Request('https://passport.weibo.cn/sso/login');
  39. req.add_header('Origin', 'https://passport.weibo.cn');
  40. 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');
  41. req.add_header('Referer', 'https://passport.weibo.cn/signin/login?entry=mweibo&res=wel&wm=3349&r=http%3A%2F%2Fm.weibo.cn%2F');
  42. with request.urlopen(req,data=login_data.encode("utf-8")) as f:
  43.     print("状态:",f.status,f.reason);
  44.     for k,v in f.getheaders():
  45.         print("%s : %s" % (k,v));
  46.     print("数据:",f.read().decode("utf-8"));
  47. senrsl@senrsl-T540p:~/test/python3$

④。。。。

14,第三方模块
都在这里注册https://pypi.python.org/pypi

1)PIL
Python Imaging Library.
Pillow.
①缩放
  1. >>> from PIL import Image;
  2. >>> im = Image.open("111111111.png");
  3. >>> w,h = im.size;
  4. >>> print("原始图像大小%s,%s" % (w,h));
  5. 原始图像大小964,787
  6. >>> im.thumbnail((w//2,h//2));
  7. >>> print("缩放一半:%s %s" % (w//2,h//2));
  8. 缩放一半:482 393
  9. >>> im.save("thumbnailllll.jpg","jpeg");

②模糊
  1. >>> from PIL import Image,ImageFilter;
  2. >>> im = Image.open("111111111.png");
  3. >>> im2 = im.filter(ImageFilter.BLUR);
  4. >>> im2.save("blur.jpg","jpeg");
  5. >>>

③生成验证码图片
  1. >>> from PIL import Image,ImageDraw,ImageFont,ImageFilter;
  2. >>> import random;
  3. >>>
  4. >>> def rndChar():
  5. ...     return chr(random.randint(65,90));
  6. ...
  7. >>> def rndColor():
  8. ...     return (random.randint(64,255),random.randint(64,255),random.randint(64,255));
  9. ...
  10. >>> def rndColor2():
  11. ...     return (random.randint(32,127),random.randint(32,127),random.randint(32,127));
  12. ...
  13. >>> width = 60*4;
  14. >>> height = 60;
  15. >>> image = Image.new("RGB",(width,height),(255,255,255));
  16. >>> font = ImageFont.truetype("Arial.ttf",36);
  17. >>> draw = ImageDraw.Draw(image);
  18. >>> for x in range(width):
  19. ...     for y in range(height):
  20. ...         draw.point((x,y),fill=rndColor());
  21. ...
  22. >>> for t in range(4):
  23. ...     draw.text((60*t +10,10),rndChar(),font=font,fill=rndColor2());
  24. ...
  25. >>> image = image.filter(ImageFilter.BLUR);
  26. >>> image.save("code.jpg","jpeg");
  27. >>>


15,virtualenv
用来配置独立的环境
1)安装环境
  1. senrsl@senrsl-T540p:~/test/python3$ sudo pip3 install virtualenv
  2. [sudo] password for senrsl:
  3. Downloading/unpacking virtualenv
  4.   Downloading virtualenv-15.0.2-py2.py3-none-any.whl (1.8MB): 1.8MB downloaded
  5. Installing collected packages: virtualenv
  6. Successfully installed virtualenv
  7. Cleaning up...
  8. senrsl@senrsl-T540p:~/test/python3$

2)创建独立项目配置独立环境
  1. senrsl@senrsl-T540p:~/test/python3$ mkdir test_virtualenv
  2. senrsl@senrsl-T540p:~/test/python3$ cd test_virtualenv/
  3. senrsl@senrsl-T540p:~/test/python3/test_virtualenv$ virtualenv --no-site-package venv
  4. Using base prefix '/usr'
  5. New python executable in /home/senrsl/test/python3/test_virtualenv/venv/bin/python3
  6. Also creating executable in /home/senrsl/test/python3/test_virtualenv/venv/bin/python
  7. Installing setuptools, pip, wheel...done.
  8. senrsl@senrsl-T540p:~/test/python3/test_virtualenv$ source venv/bin/activate
  9. (venv) senrsl@senrsl-T540p:~/test/python3/test_virtualenv$


3)回正常环境
  1. (venv) senrsl@senrsl-T540p:~/test/python3/test_virtualenv$ deactivate
  2. senrsl@senrsl-T540p:~/test/python3/test_virtualenv$

16,图形界面
支持多种图形界面的第三方库,如TK,wxWidgets,Qt,GTK等。
其中支持Tk的Tkinter是自带的。
自带的也得安。。。。
  1. senrsl@senrsl-T540p:~/test/python3$ sudo apt-get install python3-tk
  2. 正在读取软件包列表... 完成
  3. 正在分析软件包的依赖关系树      
  4. 正在读取状态信息... 完成      
  5. 将会安装下列额外的软件包:
  6.   blt
  7. 建议安装的软件包:
  8.   blt-demo tix python3-tk-dbg
  9. 下列【新】软件包将被安装:
  10.   blt python3-tk
  11. 升级了 0 个软件包,新安装了 2 个软件包,要卸载 0 个软件包,有 406 个软件包未被升级。
  12. 需要下载 576 kB 的软件包。
  13. 解压缩后会消耗掉 2,682 kB 的额外空间。
  14. 您希望继续执行吗? [Y/n] Y
  15. 获取:1 http://archive.ubuntu.com/ubuntu/ trusty/main blt amd64 2.4z-7ubuntu2 [553 kB]
  16. 获取:2 http://archive.ubuntu.com/ubuntu/ trusty-updates/main python3-tk amd64 3.4.3-1~14.04.2 [23.5 kB]
  17. 下载 576 kB,耗时 5秒 (105 kB/s)     
  18. 正在选中未选择的软件包 blt。
  19. (正在读取数据库 ... 系统当前共安装有 223603 个文件和目录。)
  20. 正准备解包 .../blt_2.4z-7ubuntu2_amd64.deb  ...
  21. 正在解包 blt (2.4z-7ubuntu2) ...
  22. 正在选中未选择的软件包 python3-tk。
  23. 正准备解包 .../python3-tk_3.4.3-1~14.04.2_amd64.deb  ...
  24. 正在解包 python3-tk (3.4.3-1~14.04.2) ...
  25. 正在处理用于 doc-base (0.10.5) 的触发器 ...
  26. Processing 1 added doc-base file...
  27. 正在处理用于 man-db (2.6.7.1-1ubuntu1) 的触发器 ...
  28. 正在设置 blt (2.4z-7ubuntu2) ...
  29. 正在设置 python3-tk (3.4.3-1~14.04.2) ...
  30. 正在处理用于 libc-bin (2.19-0ubuntu6.6) 的触发器 ...
  31. senrsl@senrsl-T540p:~/test/python3$
  32. senrsl@senrsl-T540p:~/test/python3$ vi gui/test_tkinter.py
  33. senrsl@senrsl-T540p:~/test/python3$ python3 gui/test_tkinter.py
  34. senrsl@senrsl-T540p:~/test/python3$ python3 gui/test_tkinter.py
  35. senrsl@senrsl-T540p:~/test/python3$
源码:
  1. senrsl@senrsl-T540p:~/test/python3$ cat gui/test_tkinter.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. from tkinter import *;
  5. class Application(Frame):
  6.     def __init__(self,master=None):
  7.         Frame.__init__(self,master);
  8.         self.pack();
  9.         self.createWidgets();
  10.     def createWidgets(self):
  11.         self.helloLable = Label(self,text="Hello,World!");
  12.         self.helloLable.pack();
  13.         self.quitButton = Button(self,text="退出",command=self.quit);
  14.         self.quitButton.pack();
  15. app = Application();
  16. app.master.title("你好");
  17. app.mainloop();
  18. senrsl@senrsl-T540p:~/test/python3$

然后加个可输入的提示框:


源码:
  1. senrsl@senrsl-T540p:~/test/python3$ vi gui/test_tkinter2.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 gui/test_tkinter2.py
  3. senrsl@senrsl-T540p:~/test/python3$ cat gui/test_tkinter2.py
  4. #!/usr/bin/env python3
  5. # -*- coding:utf-8 -*-
  6. from tkinter import *;
  7. import tkinter.messagebox as messagebox;
  8. class Application(Frame):
  9.     def __init__(self,master=None):
  10.         Frame.__init__(self,master);
  11.         self.pack();
  12.         self.createWidgets();
  13.     def createWidgets(self):
  14.         self.nameInput = Entry(self);
  15.         self.nameInput.pack();
  16.         self.alertButton = Button(self,text="你好啊",command=self.hello);
  17.         self.alertButton.pack();
  18.     def hello(self):
  19.         name = self.nameInput.get() or "世界";
  20.         messagebox.showinfo("消息","提示:%s" % name);
  21. app = Application();
  22. app.master.title("你好");
  23. app.mainloop();
  24. senrsl@senrsl-T540p:~/test/python3$



17,网络通信
计算机之间进程通信

1)TCP
抓取网页的例子:
  1. senrsl@senrsl-T540p:~/test/python3$ vi socket/test_tcp.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 socket/test_tcp.py
  3. HTTP/1.1 200 OK
  4. Date: Mon, 04 Jul 2016 07:06:15 GMT
  5. Content-Type: text/html
  6. Content-Length: 14613
  7. Last-Modified: Tue, 02 Sep 2014 08:55:13 GMT
  8. Connection: Close
  9. Vary: Accept-Encoding
  10. Set-Cookie: BAIDUID=2E1E25FDD3D4AB25B91E49B44DC5E6E2:FG=1; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
  11. Set-Cookie: BIDUPSID=2E1E25FDD3D4AB25B91E49B44DC5E6E2; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
  12. Set-Cookie: PSTM=1467615975; expires=Thu, 31-Dec-37 23:55:55 GMT; max-age=2147483647; path=/; domain=.baidu.com
  13. P3P: CP=" OTI DSP COR IVA OUR IND COM "
  14. Server: BWS/1.1
  15. X-UA-Compatible: IE=Edge,chrome=1
  16. Pragma: no-cache
  17. Cache-control: no-cache
  18. Accept-Ranges: bytes
  19. senrsl@senrsl-T540p:~/test/python3$ cat socket/test_tcp.py
  20. #!/usr/bin/env python3
  21. # -*- coding:utf-8 -*-
  22. import socket;
  23. s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
  24. s.connect(("www.baidu.com",80));
  25. s.send(b'GET / HTTP/1.1\r\nHost: www.baidu.com\r\nConnection: close\r\n\r\n');
  26. buffer = [];
  27. while True:
  28.     d = s.recv(1024);
  29.     if d:
  30.         buffer.append(d);
  31.     else:
  32.         break;
  33. data = b"".join(buffer);
  34. s.close();
  35. header,html = data.split(b"\r\n\r\n",1);
  36. print(header.decode("utf-8"));
  37. with open("baidu.html","wb") as f:
  38.     f.write(html);
  39. senrsl@senrsl-T540p:~/test/python3$

服务端跟客户端demo:


服务端源码:
  1. senrsl@senrsl-T540p:~/test/python3$ cat socket/echo_server.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. import socket,threading,time;
  5. def tcplink(sock,addr):
  6.     print("新连接来自%s %s...." % addr);
  7.     sock.send(b"Welcome!");
  8.     while True:
  9.         data = sock.recv(1024);
  10.         time.sleep(1);
  11.         if not data or data.decode("utf-8")=="exit":
  12.             break;
  13.         sock.send(("hello %s !" % data.decode("utf-8")).encode("utf-8"));
  14.     sock.close();
  15.     print("连接%s %s已关闭" % addr);
  16. s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
  17. s.bind(("127.0.0.1",8888));
  18. s.listen(5);
  19. print("等待连接。。。。");
  20. while True:
  21.     sock,addr = s.accept();
  22.     t = threading.Thread(target=tcplink,args=(sock,addr));
  23.     t.start();
  24. senrsl@senrsl-T540p:~/test/python3$

客户端源码:
  1. senrsl@senrsl-T540p:~/test/python3$ cat socket/echo_client.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. import socket;
  5. s = socket.socket(socket.AF_INET,socket.SOCK_STREAM);
  6. s.connect(("127.0.0.1",8888));
  7. print(s.recv(1024).decode("utf-8"));
  8. for data in [b"a",b"BBBB",b"C11",b"a1234",b"AAA",b"aBcE+"]:
  9.     s.send(data);
  10.     print((s.recv(1024).decode("utf-8")));
  11. s.send(b"exit");
  12. s.close();
  13. senrsl@senrsl-T540p:~/test/python3$



2)UDP
恩,太湖美


Server端:
  1. senrsl@senrsl-T540p:~/test/python3$ cat socket/echo_udp_server.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. import socket;
  5. s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM);
  6. s.bind(("127.0.0.1",8888));
  7. print("绑定UDP,端口8888.。。。");
  8. while True:
  9.     data,addr = s.recvfrom(1024);
  10.     print("接收%s %s...." % addr);
  11.     s.sendto(("Hello,%s" %  data.decode("utf-8")).encode("utf-8"),addr);
  12. senrsl@senrsl-T540p:~/test/python3$


Client端:
  1. senrsl@senrsl-T540p:~/test/python3$ cat socket/echo_udp_client.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. import socket;
  5. s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM);
  6. for data in [b"a",b"BBBB",b"C11",b"a1234",b"AAA",b"aBcE+"]:
  7.     s.sendto(data,("127.0.0.1",8888));
  8.     print((s.recv(1024).decode("utf-8")));
  9. s.close();
  10. 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
  1. senrsl@senrsl-T540p:~/test/python3$ vi email/test_smtp.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 email/test_smtp.py
  3. From:
  4. Password:
  5. To:
  6. SMTP Server:smtp.163.com
  7. send: 'ehlo [127.0.1.1]\r\n'
  8. reply: b'250-mail\r\n'
  9. reply: b'250-PIPELINING\r\n'
  10. reply: b'250-AUTH LOGIN PLAIN\r\n'
  11. reply: b'250-AUTH=LOGIN PLAIN\r\n'
  12. reply: b'250-coremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2Urfm2BQUCa0xDrUUUUj\r\n'
  13. reply: b'250-STARTTLS\r\n'
  14. reply: b'250 8BITMIME\r\n'
  15. reply: retcode (250); Msg: b'mail\nPIPELINING\nAUTH LOGIN PLAIN\nAUTH=LOGIN PLAIN\ncoremail 1Uxr2xKj7kG0xkI17xGrU7I0s8FY2U3Uj8Cz28x1UUUUU7Ic2I0Y2Urfm2BQUCa0xDrUUUUj\nSTARTTLS\n8BITMIME'
  16. send: 'AUTH PLAIN AHNlblJzbEAxNjMuY29tAE15ODYwMzEw\r\n'
  17. reply: b'235 Authentication successful\r\n'
  18. reply: retcode (235); Msg: b'Authentication successful'
  19. send: 'mail FROM:<senRsl@163.com>\r\n'
  20. reply: b'250 Mail OK\r\n'
  21. reply: retcode (250); Msg: b'Mail OK'
  22. send: 'rcpt TO:<senRsl@126.com>\r\n'
  23. reply: b'250 Mail OK\r\n'
  24. reply: retcode (250); Msg: b'Mail OK'
  25. send: 'data\r\n'
  26. reply: b'354 End data with <CR><LF>.<CR><LF>\r\n'
  27. reply: retcode (354); Msg: b'End data with <CR><LF>.<CR><LF>'
  28. data: (354, b'End data with <CR><LF>.<CR><LF>')
  29. 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'
  30. reply: b'250 Mail OK queued as smtp1,C9GowACHD7z2NHpXVTQJAA--.726S2 1467626743\r\n'
  31. reply: retcode (250); Msg: b'Mail OK queued as smtp1,C9GowACHD7z2NHpXVTQJAA--.726S2 1467626743'
  32. data: (250, b'Mail OK queued as smtp1,C9GowACHD7z2NHpXVTQJAA--.726S2 1467626743')
  33. send: 'quit\r\n'
  34. reply: b'221 Bye\r\n'
  35. reply: retcode (221); Msg: b'Bye'
  36. senrsl@senrsl-T540p:~/test/python3$
源码
①发普通:
  1. senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. from email import encoders;
  5. from email.header import Header;
  6. from email.mime.text import MIMEText;
  7. from email.utils import parseaddr,formataddr;
  8. import smtplib;
  9. def _format_addr(s):
  10.     name,addr = parseaddr(s);
  11.     return formataddr((Header(name,"utf-8").encode(),addr));
  12. from_addr = input("From:");
  13. password = input("Password:");
  14. to_addr = input("To:");
  15. smtp_server = input("SMTP Server:");
  16. msg = MIMEText("hello,this email send by python!","plain","utf-8");
  17. msg["From"] = _format_addr("python<%s>" % from_addr);
  18. msg["To"] = _format_addr("学习<%s>" % to_addr);
  19. msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
  20. server = smtplib.SMTP(smtp_server,25);
  21. server.set_debuglevel(1);
  22. server.login(from_addr,password);
  23. server.sendmail(from_addr,[to_addr],msg.as_string());
  24. server.quit();
  25. senrsl@senrsl-T540p:~/test/python3$


②发html:
  1. senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_html.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-

  4. from email import encoders;
  5. from email.header import Header;
  6. from email.mime.text import MIMEText;
  7. from email.utils import parseaddr,formataddr;

  8. import smtplib;

  9. def _format_addr(s):
  10.     name,addr = parseaddr(s);
  11.     return formataddr((Header(name,"utf-8").encode(),addr));



  12. from_addr = input("From:");
  13. password = input("Password:");

  14. to_addr = input("To:");
  15. smtp_server = input("SMTP Server:");


  16. msg = MIMEText("<html><body>hello,this <b>email</b> send by python!</body></html>","html","utf-8");
  17. msg["From"] = _format_addr("python<%s>" % from_addr);
  18. msg["To"] = _format_addr("学习<%s>" % to_addr);
  19. msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();

  20. server = smtplib.SMTP(smtp_server,25);
  21. server.set_debuglevel(1);
  22. server.login(from_addr,password);
  23. server.sendmail(from_addr,[to_addr],msg.as_string());
  24. server.quit();
  25. senrsl@senrsl-T540p:~/test/python3$

③发附件
  1. senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_annex.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. from email import encoders;
  5. from email.header import Header;
  6. from email.mime.text import MIMEText;
  7. from email.mime.multipart import MIMEMultipart;
  8. from email.mime.base import MIMEBase;
  9. from email.utils import parseaddr,formataddr;
  10. import smtplib;
  11. def _format_addr(s):
  12.     name,addr = parseaddr(s);
  13.     return formataddr((Header(name,"utf-8").encode(),addr));
  14. from_addr = input("From:");
  15. password = input("Password:");
  16. to_addr = input("To:");
  17. smtp_server = input("SMTP Server:");
  18. msg = MIMEMultipart();
  19. #msg = MIMEText("hello,this email send by python!","plain","utf-8");
  20. msg["From"] = _format_addr("是python<%s>" % from_addr);
  21. msg["To"] = _format_addr("来自学习<%s>" % to_addr);
  22. msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
  23. msg.attach(MIMEText("hello,this email send by python!","plain","utf-8"));
  24. #添加附件
  25. with open("/home/senrsl/test/python3/111111111.png","rb") as f:
  26.     mime = MIMEBase("image","png",filename="111111111.png");
  27.     #头信息
  28.     mime.add_header("Content-Dispostion","attachment",filename="111111111.png");
  29.     mime.add_header("Content-ID","<0>");
  30.     mime.add_header("X-Attachment-Id","0");
  31.     #读取附件内容
  32.     mime.set_payload(f.read());
  33.     #编码
  34.     encoders.encode_base64(mime);
  35.     #添加到MIMEMultipart
  36.     msg.attach(mime);
  37. server = smtplib.SMTP(smtp_server,25);
  38. server.set_debuglevel(1);
  39. server.login(from_addr,password);
  40. server.sendmail(from_addr,[to_addr],msg.as_string());
  41. server.quit();
  42. senrsl@senrsl-T540p:~/test/python3$




④发图片
  1. senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_img.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. from email import encoders;
  5. from email.header import Header;
  6. from email.mime.text import MIMEText;
  7. from email.mime.multipart import MIMEMultipart;
  8. from email.mime.base import MIMEBase;
  9. from email.utils import parseaddr,formataddr;
  10. import smtplib;
  11. def _format_addr(s):
  12.     name,addr = parseaddr(s);
  13.     return formataddr((Header(name,"utf-8").encode(),addr));
  14. from_addr = input("From:");
  15. password = input("Password:");
  16. to_addr = input("To:");
  17. smtp_server = input("SMTP Server:");
  18. msg = MIMEMultipart();
  19. #msg = MIMEText("hello,this email send by python!","plain","utf-8");
  20. msg["From"] = _format_addr("是python<%s>" % from_addr);
  21. msg["To"] = _format_addr("来自学习<%s>" % to_addr);
  22. msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
  23. msg.attach(MIMEText("<html><body>hello,this email send by python!<br/>图片是<img src='cid:0'/></body></html>","html","utf-8"));
  24. #添加附件
  25. with open("/home/senrsl/test/python3/111111111.png","rb") as f:
  26.     mime = MIMEBase("image","png",filename="111111111.png");
  27.     #头信息
  28.     mime.add_header("Content-Dispostion","attachment",filename="111111111.png");
  29.     mime.add_header("Content-ID","<0>");
  30.     mime.add_header("X-Attachment-Id","0");
  31.     #读取附件内容
  32.     mime.set_payload(f.read());
  33.     #编码
  34.     encoders.encode_base64(mime);
  35.     #添加到MIMEMultipart
  36.     msg.attach(mime);
  37. server = smtplib.SMTP(smtp_server,25);
  38. server.set_debuglevel(1);
  39. server.login(from_addr,password);
  40. server.sendmail(from_addr,[to_addr],msg.as_string());
  41. server.quit();
  42. senrsl@senrsl-T540p:~/test/python3$

图片是附件,然后html加img标签,src为cid:0,cid:1。。。。

⑤同时支持html和plain
  1. senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_html1plain.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. from email import encoders;
  5. from email.header import Header;
  6. from email.mime.text import MIMEText;
  7. from email.mime.multipart import MIMEMultipart;
  8. from email.utils import parseaddr,formataddr;
  9. import smtplib;
  10. def _format_addr(s):
  11.     name,addr = parseaddr(s);
  12.     return formataddr((Header(name,"utf-8").encode(),addr));
  13. from_addr = input("From:");
  14. password = input("Password:");
  15. to_addr = input("To:");
  16. smtp_server = input("SMTP Server:");
  17. msg = MIMEMultipart("alternative");
  18. msg["From"] = _format_addr("python<%s>" % from_addr);
  19. msg["To"] = _format_addr("学习<%s>" % to_addr);
  20. msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
  21. msg.attach(MIMEText("hello,this如果客户端版本旧不支持html就显示这个文本 ","plain","utf-8"));
  22. msg.attach(MIMEText("<html><body>hello,this <b>email</b> send by python!</body></html>","html","utf-8"));
  23. server = smtplib.SMTP(smtp_server,25);
  24. server.set_debuglevel(1);
  25. server.login(from_addr,password);
  26. server.sendmail(from_addr,[to_addr],msg.as_string());
  27. server.quit();
  28. senrsl@senrsl-T540p:~/test/python3$




⑥加密smtp
163连不上服务器,可能还得需要证书吧。。。。
  1. senrsl@senrsl-T540p:~/test/python3$ python3 email/test_smtp_ttls.py
  2. 。。。。
  3. Traceback (most recent call last):
  4.   File "email/test_smtp_ttls.py", line 30, in <module>
  5.     server = smtplib.SMTP(smtp_server,smtp_port);
  6.   File "/usr/lib/python3.4/smtplib.py", line 242, in __init__
  7.     (code, msg) = self.connect(host, port)
  8.   File "/usr/lib/python3.4/smtplib.py", line 323, in connect
  9.     (code, msg) = self.getreply()
  10.   File "/usr/lib/python3.4/smtplib.py", line 376, in getreply
  11.     raise SMTPServerDisconnected("Connection unexpectedly closed")
  12. smtplib.SMTPServerDisconnected: Connection unexpectedly closed
  13. senrsl@senrsl-T540p:~/test/python3$ vi email/test_smtp_ttls.py
  14. senrsl@senrsl-T540p:~/test/python3$ cat email/test_smtp_ttls.py
  15. #!/usr/bin/env python3
  16. # -*- coding:utf-8 -*-
  17. from email import encoders;
  18. from email.header import Header;
  19. from email.mime.text import MIMEText;
  20. from email.utils import parseaddr,formataddr;
  21. import smtplib;
  22. def _format_addr(s):
  23.     name,addr = parseaddr(s);
  24.     return formataddr((Header(name,"utf-8").encode(),addr));
  25. from_addr = input("From:");
  26. password = input("Password:");
  27. to_addr = input("To:");
  28. smtp_server = "smtp.163.com";
  29. smtp_port = 465;#465/994
  30. msg = MIMEText("hello,this email send by python!","plain","utf-8");
  31. msg["From"] = _format_addr("python<%s>" % from_addr);
  32. msg["To"] = _format_addr("学习<%s>" % to_addr);
  33. msg["Subject"] = Header("来自SMTP,没标题就554","utf-8").encode();
  34. server = smtplib.SMTP(smtp_server,smtp_port);
  35. server.starttls();
  36. server.set_debuglevel(1);
  37. server.login(from_addr,password);
  38. server.sendmail(from_addr,[to_addr],msg.as_string());
  39. server.quit();
  40. senrsl@senrsl-T540p:~/test/python3$


2)POP3收取邮件
①用poplib把邮件原始文本下载到本地;
②用email解析原始文本,还原为邮件对象。

  1. senrsl@senrsl-T540p:~/test/python3$ cat email/test_pop3_resovle.py
  2. #!/usr/bin/env python3
  3. # -*- coding:utf-8 -*-
  4. import poplib;
  5. from email.parser import Parser;
  6. from email.header import decode_header;
  7. from email.utils import parseaddr;
  8. def decode_str(s):
  9.     value,charset = decode_header(s)[0];
  10.     if charset:
  11.         value = value.decode(charset);
  12.     return value;
  13. def guess_charset(msg):
  14.     charset = msg.get_charset();
  15.     if charset is None:
  16.         content_type = msg.get("Content-Type","").lower();
  17.         pos = content_type.find("charset=");
  18.         if pos >=0:
  19.             charset = content_type[pos+8:].strip();
  20.         return charset;
  21. def print_info(msg,indent=0):
  22.     if indent ==0:
  23.         for header in ["From","To","Subject"]:
  24.             value = msg.get(header,"");
  25.             print("header的value是:",value);
  26.             if value:
  27.                 if header == "Subject":
  28.                     value = decode_str(value);
  29.                 else:
  30.                     hdr,addr = parseaddr(value);
  31.                     name = decode_str(hdr);
  32.                     value = u"%s <%s>" %  (name,addr);
  33.             print("%s %s: %s" % (' ' * indent,header,value));
  34.     if (msg.is_multipart()):
  35.         parts = msg.get_payload();
  36.         for n,part in enumerate(path):
  37.             print("%spart %s" % (" " * indent,n ));
  38.             print("%s-----------" % (" " * indent));
  39.             print_info(part,indent+1);
  40.     else:
  41.         content_type = msg.get_content_type();
  42.         if content_type == "text/plain" or content_type == "text/html":
  43.             content = msg.get_payload(decode=True);
  44.             charset = guess_charset(msg);
  45.             if charset:
  46.                 content = content.decode(charset);
  47.             print("%s 内容: %s" % (" " * indent,content+"...."));
  48.         else:
  49.             print("%s Attachment:%s" % (" " * indent,content_type));
  50. email = input("邮箱:");
  51. password = input("密码: ");
  52. pop3_server = input("POP服务器地址:");
  53. #连接到pop3服务器
  54. server = poplib.POP3(pop3_server);
  55. #调试信息
  56. server.set_debuglevel(1);
  57. #打印pop3的欢迎文字
  58. print(server.getwelcome().decode("utf-8"));
  59. #身份认证
  60. server.user(email);
  61. server.pass_(password);
  62. #stat()返回邮件数量和占用空间
  63. print("消息 %s,大小:%s" % server.stat());
  64. #所有邮件编号
  65. resp,mails,octets = server.list();
  66. #可以查看返回的编号列表类似
  67. #print(mails);
  68. #获取最后一封邮件
  69. index = len(mails);
  70. resp,lines,octets = server.retr(index);
  71. #lines存储邮件的原始文本的每一行
  72. #可以获得整个邮件的原始文本
  73. msg_content = b"\r\n".join(lines).decode("utf-8");
  74. #解析邮件
  75. msg = Parser().parsestr(msg_content);
  76. print_info(msg);
  77. #可以根据邮件索引直接从服务器删除邮件
  78. #server.dele(index);
  79. #关闭连接
  80. server.quit();
  81. senrsl@senrsl-T540p:~/test/python3$
那个循环是从头里取,不要改文字啊。。。。


19,数据库
网状数据库-->层次数据库-->关系数据库

1)SQLite
内置了sqlite3
  1. senrsl@senrsl-T540p:~/test/python3$ mkdir db
  2. senrsl@senrsl-T540p:~/test/python3$ cd db
  3. senrsl@senrsl-T540p:~/test/python3/db$ python3
  4. Python 3.4.3 (default, Oct 14 2015, 20:28:29)
  5. [GCC 4.8.4] on linux
  6. Type "help", "copyright", "credits" or "license" for more information.
  7. >>>
  8. >>>
  9. >>> import sqlite3;
  10. >>> conn = sqlite3.connect("test.db");
  11. >>> cursor = conn.cursor();
  12. >>> cursor.execute("create table user(id varchar(20) primary key,name varchar(20))");
  13. <sqlite3.Cursor object at 0x7f354cd722d0>
  14. >>> cursor.execute("insert into user (id,name) values (\"1\",\"fuck\")");
  15. <sqlite3.Cursor object at 0x7f354cd722d0>
  16. >>> cursor.rowcount;
  17. 1
  18. >>> cursor.close();
  19. >>> conn.commit();
  20. >>> conn.close();
  21. >>>
  22. >>> conn = sqlite3.connect("test.db");
  23. >>> cursor = conn.cursor();
  24. >>> cursor.execute("select * from user where id = ?",("1"));
  25. <sqlite3.Cursor object at 0x7f354b6c0f80>
  26. >>> values = cursor.fetchall();
  27. >>> values
  28. [('1', 'fuck')]
  29. >>> cursor.close();
  30. >>> conn.close();
  31. >>>

2)MySQL
需要安装驱动
  1. senrsl@senrsl-T540p:~/test/python3/db$ pip3 install mysql-connector-python --allow-external mysql-connector-python
  2. Downloading/unpacking mysql-connector-python
  3.   Could not find any downloads that satisfy the requirement mysql-connector-python
  4. Cleaning up...
  5. No distributions at all found for mysql-connector-python
  6. Storing debug log for failure in /home/senrsl/.pip/pip.log
  7. senrsl@senrsl-T540p:~/test/python3/db$
然后手动下载
https://pypi.python.org/pypi/mysql-connector-python/2.0.4
解压,执行
  1. senrsl@senrsl-T540p:~/test/python3/db/mysql-connector-python-2.0.4$ sudo python3 setup.py install
  2. [sudo] password for senrsl:
  3. ....
一开始怎么都找不到,教程是 sudo python setup....
现在的命令环境是python3....

就好了
  1. senrsl@senrsl-T540p:~/test/python3/db$ python3
  2. Python 3.4.3 (default, Oct 14 2015, 20:28:29)
  3. [GCC 4.8.4] on linux
  4. Type "help", "copyright", "credits" or "license" for more information.
  5. >>>
  6. >>> import mysql.connector;
  7. >>> conn = mysql.connector.connect(host="10.1.8.102",user="root",password="0123",database="test");
  8. >>> cursor = conn.cursor();
  9. >>> cursor.execute("create table user(id varchar(20) primary key,name varchar(20))");
  10. >>> cursor.execute("insert into user(id,name) values(%s,%s)",["1","fuck"]);
  11. >>> cursor.rowcount
  12. 1
  13. >>> conn.commit();
  14. >>> cursor.close();
  15. True
  16. >>>
  17. >>> cursor = conn.cursor();
  18. >>> cursor.execute("select * from user where id = %s",("1",));
  19. >>> values = cursor.fetchall();
  20. >>> values
  21. [('1', 'fuck')]
  22. >>> cursor.close();
  23. True
  24. >>> conn.close();
  25. >>>
数据库用的视频聊天demo服务器上的测试数据库

3)使用SQLAlchemy框架
这是一个ORM框架
ORM:Object-Relational Mapping.
安装:
  1. senrsl@senrsl-T540p:~/test/python3/db$ sudo pip3 install sqlalchemy
  2. [sudo] password for senrsl:
使用:
  1. >>> from sqlalchemy import Column,String,create_engine;
  2. >>> from sqlalchemy.orm import sessionmaker;
  3. >>> from sqlalchemy.ext.declarative import declarative_base;
  4. >>>
  5. >>> Base = declarative_base();
  6. >>> class User(Base):
  7. ...     __tablename__ = "user";
  8. ...     id = Column(String(20),primary_key=True);
  9. ...     name = Column(String(20));
  10. ...
  11. >>> engine = create_engine("mysql+mysqlconnector://root:0123@10.1.8.102:3306/test");
  12. >>> DBSession = sessionmaker(bind=engine);
  13. >>>
  14. >>> session = DBSession();
  15. >>> new_user = User(id="3",name="啊啊");
  16. >>> session.add(new_user);
  17. >>> session.commit();
  18. >>> session.close();
  19. >>>
  20. >>> session = DBSession();
  21. >>> user = session.query(User).filter(User.id=="3").one();
  22. >>> print("type",type(user));
  23. type <class '__main__.User'>
  24. >>> print("name:",user.name);
  25. name: 啊啊
  26. >>> session.close();
  27. >>>
一个封装

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服务
  1. senrsl@senrsl-T540p:~/test/python3$ python3 web/test_wsgi_server.py
  2. 模块wsgiref,纯python编写的WSGI服务器的参考实现
  3. 所谓"参考实现"是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使用
  4. 服务运行在8080上。。。。
  5. 127.0.0.1 - - [06/Jul/2016 17:09:26] "GET / HTTP/1.1" 200 19
  6. 127.0.0.1 - - [06/Jul/2016 17:09:26] "GET /favicon.ico HTTP/1.1" 200 27
  7. 127.0.0.1 - - [06/Jul/2016 17:09:43] "GET /aaaaaa HTTP/1.1" 200 22
  8. 127.0.0.1 - - [06/Jul/2016 17:09:43] "GET /favicon.ico HTTP/1.1" 200 27
  9. ^Z
  10. [1]+  已停止               python3 web/test_wsgi_server.py
  11. senrsl@senrsl-T540p:~/test/python3$ cat web/test_wsgi_server.py
  12. #!/usr/bin/env python3
  13. # -*- coding:utf-8 -*-
  14. print("模块wsgiref,纯python编写的WSGI服务器的参考实现");
  15. print("所谓"参考实现"是指该实现完全符合WSGI标准,但是不考虑任何运行效率,仅供开发和测试使 用");
  16. from wsgiref.simple_server import make_server;
  17. from test_wsgi_hello import application;
  18. #IP地址,端口,处理函数
  19. httpd = make_server("",8080,application);
  20. print("服务运行在%s上。。。。" % 8080);
  21. #启动监听
  22. httpd.serve_forever();
  23. senrsl@senrsl-T540p:~/test/python3$ cat web/test_wsgi_hello.py
  24. #!/usr/bin/env python3
  25. # -*- coding:utf-8 -*-
  26. def application(environ,start_response):
  27.     start_response("200 OK",[("Content-Type","text/html")]);
  28.     body = "<h1>Hello,%s!</h1>" % (environ["PATH_INFO"][1:] or "web");
  29. #    return [b"<h1>Hello,web!</h1>"];
  30.     return [body.encode("utf-8")];
  31. senrsl@senrsl-T540p:~/test/python3$
效果:



2)框架Flask
安装库:
  1. senrsl@senrsl-T540p:~/test/python3$ sudo pip3 install flask

使用:
  1. senrsl@senrsl-T540p:~/test/python3$ vi web/test_flask.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 web/test_flask.py
  3.  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
  4. 127.0.0.1 - - [06/Jul/2016 17:32:42] "GET / HTTP/1.1" 200 -
  5. 127.0.0.1 - - [06/Jul/2016 17:32:42] "GET /favicon.ico HTTP/1.1" 404 -
  6. 127.0.0.1 - - [06/Jul/2016 17:32:48] "GET / HTTP/1.1" 200 -
  7. 127.0.0.1 - - [06/Jul/2016 17:33:05] "GET /signin HTTP/1.1" 200 -
  8. 127.0.0.1 - - [06/Jul/2016 17:33:11] "POST /signin HTTP/1.1" 200 -
  9. 127.0.0.1 - - [06/Jul/2016 17:33:13] "GET /signin HTTP/1.1" 200 -
  10. 127.0.0.1 - - [06/Jul/2016 17:33:28] "POST /signin HTTP/1.1" 200 -
  11. 127.0.0.1 - - [06/Jul/2016 17:33:29] "GET /signin HTTP/1.1" 200 -
  12. 127.0.0.1 - - [06/Jul/2016 17:33:35] "POST /signin HTTP/1.1" 200 -
  13. 127.0.0.1 - - [06/Jul/2016 17:33:37] "GET /signin HTTP/1.1" 200 -
  14. 127.0.0.1 - - [06/Jul/2016 17:33:55] "POST /signin HTTP/1.1" 200 -
  15. 127.0.0.1 - - [06/Jul/2016 17:33:57] "GET /signin HTTP/1.1" 200 -
  16. ^Z
  17. [2]+  已停止               python3 web/test_flask.py
  18. senrsl@senrsl-T540p:~/test/python3$ cat web/test_flask.py
  19. #!/usr/bin/env python3
  20. # -*- coding:utf-8 -*-
  21. from flask import Flask;
  22. from flask import request;
  23. app = Flask(__name__);
  24. @app.route("/",methods=["GET","POST"])
  25. def home():
  26.     return "<h1>Home</h1>";
  27. @app.route("/signin",methods=["GET"])
  28. def signin_form():
  29.     return """<form action='/signin' method='post'>
  30.         <p><input name='username'/></p>
  31.         <p><input name='password' type='password'/></p>
  32.         <p><button type='submit'>登陆</button></p>
  33.         </form>""";
  34. @app.route("/signin",methods=["POST"])
  35. def signin():
  36.     if request.form["username"]=="admin" and request.form["password"] =="passwd":
  37.         return "<h3>Hello,admin</h3>";
  38.     return "<h3>密码错误</h3>";
  39. if __name__ == "__main__":
  40.     app.run();
  41. senrsl@senrsl-T540p:~/test/python3$
常见的Web框架:
Django,web.py,Bottle,Tomado.

3)模板Jinja2
要看目录结构,不看结构浪费好久
  1. senrsl@senrsl-T540p:~$ cd test/python3/
  2. senrsl@senrsl-T540p:~/test/python3$ python3 web/test_flask_mvc.py
  3.  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
  4. 127.0.0.1 - - [06/Jul/2016 20:32:53] "GET / HTTP/1.1" 200 -
  5. 127.0.0.1 - - [06/Jul/2016 20:32:59] "GET /signin HTTP/1.1" 200 -
  6. 127.0.0.1 - - [06/Jul/2016 20:33:01] "POST /signin HTTP/1.1" 200 -
  7. 127.0.0.1 - - [06/Jul/2016 20:33:04] "POST /signin HTTP/1.1" 200 -
  8. 127.0.0.1 - - [06/Jul/2016 20:33:09] "POST /signin HTTP/1.1" 200 -
  9. ^Z
  10. [1]+  已停止               python3 web/test_flask_mvc.py
  11. senrsl@senrsl-T540p:~/test/python3$ cat web/test_flask_mvc.py
  12. #!/usr/bin/env python3
  13. # -*- coding:utf-8 -*-
  14. from flask import Flask,request,render_template
  15. app = Flask(__name__);
  16. @app.route("/",methods=["GET","POST"])
  17. def home():
  18.     return render_template("test_flask_mvc_home.html");
  19. @app.route("/signin",methods=["GET"])
  20. def signin_form():
  21.     return render_template("test_flask_mvc_form.html");
  22. @app.route("/signin",methods=["POST"])
  23. def signin():
  24.     username = request.form["username"];
  25.     password = request.form["password"];
  26.     if username == "admin" and password=="passwd":
  27.         return render_template("test_flask_mvc_sigin_suss.html",username=username);
  28.     return render_template("test_flask_mvc_form.html",message="错误用户名或密 码",username=username);
  29. if __name__ =="__main__":
  30.     app.run();
  31. senrsl@senrsl-T540p:~/test/python3$ cat web/templates/test_flask_mvc_home.html
  32. <html>
  33. <head>
  34.   <title>Home</title>
  35. </head>
  36. <body>
  37.   <h1 style="font-style:italic">Home</h1>
  38. </body>
  39. </html>
  40. senrsl@senrsl-T540p:~/test/python3$ cat web/templates/test_flask_mvc_sigin_suss.html
  41. <html>
  42. <head>
  43.   <title>Welcome, {{ username }}</title>
  44. </head>
  45. <body>
  46.   <p>Welcome, {{ username }}!</p>
  47. </body>
  48. </html>
  49. senrsl@senrsl-T540p:~/test/python3$ cat web/templates/test_flask_mvc_form.html
  50. <html>
  51. <head>
  52.   <title>Please Sign In</title>
  53. </head>
  54. <body>
  55.   {% if message %}
  56.   <p style="color:red">{{ message }}</p>
  57.   {% endif %}
  58.   <form action="/signin" method="post">
  59.     <legend>Please sign in:</legend>
  60.     <p><input name="username" placeholder="Username" value="{{ username }}"></p>
  61.     <p><input name="password" placeholder="Password" type="password"></p>
  62.     <p><button type="submit">Sign In</button></p>
  63.   </form>
  64. </body>
  65. </html>
  66. senrsl@senrsl-T540p:~/test/python3$
常见的模板还有:
Mako,Cheetah,Django等。。。。


21,异步IO


1)协程
微线程,纤程,coroutine [kəru:'ti:n ]。

进程:

进程之间不共享任何状态,进程的调度由操作系统完成,每个进程都有自己独立的内存空间,进程间通讯主要是通过信号传递的方式来实现的,实现方 式有多种,信号量、管道、事件等,任何一种方式的通讯效率都需要过内核,导致通讯效率比较低。由于是独立的内存空间,上下文切换的时候需要保 存先调用栈的信息、cpu各寄存器的信息、虚拟内存、以及打开的相关句柄等信息,所以导致上下文进程间切换开销很大,通讯麻烦。


线程:

线程之间共享变量,解决了通讯麻烦的问题,但是对于变量的访问需要锁,线程的调度主要也是有操作系统完成,一个进程可以拥有多个线程,但是其 中每个线程会共享父进程像操作系统申请资源,这个包括虚拟内存、文件等,由于是共享资源,所以创建线程所需要的系统资源占用比进程小很多,相 应的可创建的线程数量也变得相对多很多。线程时间的通讯除了可以使用进程之间通讯的方式以外还可以通过共享内存的方式进行通信,所以这个速度 比通过内核要快很多。另外在调度方面也是由于内存是共享的,所以上下文切换的时候需要保存的东西就像对少一些,这样一来上下文的切换也变得高 效。


协程:

协程的调度完全由用户控制,一个线程可以有多个协程,用户创建了几个线程,然后每个线程都是循环按照指定的任务清单顺序完成不同的任务,当任 务被堵塞的时候执行下一个任务,当恢复的时候再回来执行这个任务,任务之间的切换只需要保存每个任务的上下文内容,就像直接操作栈一样的,这 样就完全没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快;另外协程还需要保证是非堵塞的且没有相互依赖,协程基本上 不能同步通讯,多采用一步的消息通讯,效率比较高。

这是协程的一个示例:
  1. senrsl@senrsl-T540p:~/test/python3$ python3
  2. Python 3.4.3 (default, Oct 14 2015, 20:28:29)
  3. [GCC 4.8.4] on linux
  4. Type "help", "copyright", "credits" or "license" for more information.
  5. >>> def consumer():
  6. ...     r = "";
  7. ...     while True:
  8. ...         n = yield r;
  9. ...         if not n:
  10. ...             return;
  11. ...         print("[消费者]Consuming %s...." % n);
  12. ...         r = "200 OK";
  13. ...
  14. >>> def produce(c):
  15. ...     c.send(None);
  16. ...     n = 0;
  17. ...     while n <5:
  18. ...         n = n+1;
  19. ...         print("[生产者]Producing %s...." % n);
  20. ...         r = c.send(n);
  21. ...         print("[生产者2]Consumer return %s" % r);
  22. ...     c.close();
  23. ...
  24. >>> c = consumer();
  25. >>> produce(c);
  26. [生产者]Producing 1....
  27. [消费者]Consuming 1....
  28. [生产者2]Consumer return 200 OK
  29. [生产者]Producing 2....
  30. [消费者]Consuming 2....
  31. [生产者2]Consumer return 200 OK
  32. [生产者]Producing 3....
  33. [消费者]Consuming 3....
  34. [生产者2]Consumer return 200 OK
  35. [生产者]Producing 4....
  36. [消费者]Consuming 4....
  37. [生产者2]Consumer return 200 OK
  38. [生产者]Producing 5....
  39. [消费者]Consuming 5....
  40. [生产者2]Consumer return 200 OK
  41. >>>

2)asyncio
python3.4引入,内置对异步IO支持
demo:
  1. >>> import asyncio;
  2. >>> @asyncio.coroutine
  3. ... def hello():
  4. ...     print("hello world!");
  5. ...     r = yield from asyncio.sleep(1);
  6. ...     print("hello again!");
  7. ...
  8. >>> loop = asyncio.get_event_loop();
  9. >>> loop.run_until_complete(hello());
  10. hello world!
  11. hello again!
  12. >>> loop.close();
  13. >>>
用Task封装看效果:
  1. senrsl@senrsl-T540p:~/test/python3$ python3
  2. Python 3.4.3 (default, Oct 14 2015, 20:28:29)
  3. [GCC 4.8.4] on linux
  4. Type "help", "copyright", "credits" or "license" for more information.
  5. >>>
  6. >>> import threading;
  7. >>> import asyncio;
  8. >>> @asyncio.coroutine
  9. ... def hello():
  10. ...     print("Hello world %s !" % threading.currentThread());
  11. ...     yield from asyncio.sleep(1);
  12. ...     print("Hello again %s !" % threading.currentThread());
  13. ...
  14. >>> loop = asyncio.get_event_loop();
  15. >>> tasks = [hello(),hello()];
  16. >>> loop.run_until_complete(asyncio.wait(tasks));
  17. Hello world <_MainThread(MainThread, started 140178258724672)> !
  18. Hello world <_MainThread(MainThread, started 140178258724672)> !
  19. Hello again <_MainThread(MainThread, started 140178258724672)> !
  20. Hello again <_MainThread(MainThread, started 140178258724672)> !
  21. ({<Task finished coro=<hello() done, defined at <stdin>:1> result=None>, <Task finished coro=<hello() done, defined at <stdin>:1> result=None>}, set())
  22. >>> loop.close();
  23. >>>

异步获取仨网站的首页:
  1. senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_asynicio.py
  2. wget www.sohu.com....
  3. wget www.sina.com.cn....
  4. wget www.163.com....
  5. www.sohu.com header > HTTP/1.1 200 OK
  6. www.sohu.com header > Content-Type: text/html
  7. www.sohu.com header > Content-Length: 91589
  8. www.sohu.com header > Connection: close
  9. www.sohu.com header > Date: Thu, 07 Jul 2016 10:28:48 GMT
  10. www.sohu.com header > Server: SWS
  11. www.sohu.com header > Vary: Accept-Encoding
  12. www.sohu.com header > Cache-Control: no-transform, max-age=120
  13. www.sohu.com header > Expires: Thu, 07 Jul 2016 10:30:48 GMT
  14. www.sohu.com header > Last-Modified: Thu, 07 Jul 2016 10:28:10 GMT
  15. www.sohu.com header > Content-Encoding: gzip
  16. www.sohu.com header > X-RS: 10587158.19762208.11340962
  17. www.sohu.com header > FSS-Cache: HIT from 7965678.14519288.8719442
  18. www.sohu.com header > FSS-Proxy: Powered by 2722718.4033448.3476402
  19. www.163.com header > HTTP/1.0 302 Moved Temporarily
  20. www.163.com header > Server: Cdn Cache Server V2.0
  21. www.163.com header > Date: Thu, 07 Jul 2016 10:29:45 GMT
  22. www.163.com header > Content-Length: 0
  23. www.163.com header > Location: http://www.163.com/special/0077jt/error_isp.html
  24. www.163.com header > Connection: close
  25. www.sina.com.cn header > HTTP/1.1 200 OK
  26. www.sina.com.cn header > Content-Type: text/html
  27. www.sina.com.cn header > Vary: Accept-Encoding
  28. www.sina.com.cn header > X-Powered-By: shci_v1.03
  29. www.sina.com.cn header > Server: nginx
  30. www.sina.com.cn header > Date: Thu, 07 Jul 2016 10:29:12 GMT
  31. www.sina.com.cn header > Last-Modified: Thu, 07 Jul 2016 10:27:53 GMT
  32. www.sina.com.cn header > Expires: Thu, 07 Jul 2016 10:30:12 GMT
  33. www.sina.com.cn header > Cache-Control: max-age=60
  34. www.sina.com.cn header > Age: 33
  35. www.sina.com.cn header > Content-Length: 600183
  36. www.sina.com.cn header > X-Cache: HIT from cnc.tj.1cf2.93.spool.sina.com.cn
  37. www.sina.com.cn header > Connection: close
  38. senrsl@senrsl-T540p:~/test/python3$ cat asyncio/test_asynicio.py
  39. #!/usr/bin/env python3
  40. # -*- coding:utf-8 -*-
  41. import asyncio;
  42. @asyncio.coroutine
  43. def wget(host):
  44.     print("wget %s...." % host);
  45.     connect = asyncio.open_connection(host,80);
  46.     reader,writer = yield from connect;
  47.     header = "GET / HTTP/1.0\r\nHost: %s\r\n\r\n" % host;
  48.     writer.write(header.encode("utf-8"));
  49.     yield from writer.drain();
  50.     while True:
  51.         line = yield from reader.readline();
  52.         if line == b"\r\n":
  53.             break;
  54.         print("%s header > %s" % (host,line.decode("utf-8").rstrip()));
  55.     writer.close();
  56. loop = asyncio.get_event_loop();
  57. tasks = [wget(host) for host in ["www.sina.com.cn","www.sohu.com","www.163.com"]];
  58. loop.run_until_complete(asyncio.wait(tasks));
  59. loop.close();
  60. senrsl@senrsl-T540p:~/test/python3$
少写一个空格找半天。。。。

回到第一节重新看。。。。
  1. senrsl@senrsl-T540p:~/test/python3$ vi asyncio/test_coroutine.py
  2. senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_coroutine.py
  3. [生产者]1....
  4. [消费者]1....
  5. [生产者]  return 200 OK......
  6. [生产者]2....
  7. [消费者]2....
  8. [生产者]  return 200 OK......
  9. [生产者]3....
  10. [消费者]3....
  11. [生产者]  return 200 OK......
  12. [生产者]4....
  13. [消费者]4....
  14. [生产者]  return 200 OK......
  15. [生产者]5....
  16. [消费者]5....
  17. [生产者]  return 200 OK......
  18. senrsl@senrsl-T540p:~/test/python3$
  19. senrsl@senrsl-T540p:~/test/python3$ vi asyncio/test_asyncio_demo.py
  20. senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_asyncio_demo.py
  21. hello,world!!!!!
  22. hello again!
  23. senrsl@senrsl-T540p:~/test/python3$
  24. senrsl@senrsl-T540p:~/test/python3$ cp asyncio/test_asyncio_demo.py asyncio/test_asyncio_thread.py
  25. senrsl@senrsl-T540p:~/test/python3$ vi asyncio/test_asyncio_thread.py
  26. senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_asyncio_thread.py
  27. hello,world!!!!! <_MainThread(MainThread, started 140340961548096)>
  28. hello,world!!!!! <_MainThread(MainThread, started 140340961548096)>
  29. hello again! <_MainThread(MainThread, started 140340961548096)>
  30. hello again! <_MainThread(MainThread, started 140340961548096)>
  31. senrsl@senrsl-T540p:~/test/python3$
好像有点明白了
貌似一条线程,顺序执行下的非阻塞任务。。。。

3)async/await
从3.5之后引入了新的语法async和await,最大的好处是单词短了好认
①把@asyncio.coroutine这个注解替换成async这个关键字;
②把yield from替换成await;
即可无痛升级到3.5短版。

4)aiohttp
基于asyncio实现的http框架。
安装:
  1. senrsl@senrsl-T540p:~/test/python3$ sudo pip3 install aiohttp
执行:
  1. senrsl@senrsl-T540p:~$ cd test/python3/
  2. senrsl@senrsl-T540p:~/test/python3$ python3 asyncio/test_aiohttp.py
  3. Server started at http://127.0.0.1:8888....
  4. ^Z
  5. [1]+  已停止               python3 asyncio/test_aiohttp.py
  6. senrsl@senrsl-T540p:~/test/python3$ cat asyncio/test_aiohttp.py
  7. #!/usr/bin/env python3
  8. # -*- coding:utf-8 -*-
  9. import asyncio;
  10. from aiohttp import web;
  11. @asyncio.coroutine
  12. def index(request):
  13.     yield from asyncio.sleep(0.5);
  14.     return web.Response(body=b"<h1>Index</h1>");
  15. @asyncio.coroutine
  16. def hello(request):
  17.     yield from asyncio.sleep(0.5);
  18.     text = "<h1>你好%s</h1>" % request.match_info["name"];
  19.     return web.Response(body=text.encode("utf-8"));
  20. @asyncio.coroutine
  21. def init(loop):
  22.     app = web.Application(loop=loop);
  23.     app.router.add_route("GET","/",index);
  24.     app.router.add_route("GET","/hello/{name}",hello);
  25.     srv = yield from loop.create_server(app.make_handler(),"127.0.0.1",8888);
  26.     print("Server started at http://127.0.0.1:8888....");
  27.     return srv;
  28. loop = asyncio.get_event_loop();
  29. loop.run_until_complete(init(loop));
  30. loop.run_forever();
  31. senrsl@senrsl-T540p:~/test/python3$
效果:


教程终于看完了。。。。

教程里的项目实战准备。
2016年07月08日17:52:20





--
senRsl
2016年06月29日10:15:34

没有评论 :

发表评论