1、同时运行多个任务有两种基本做法:进程分支和线程派生。
2、windows下的Python标准版不支持进程分支。
3、分支的进程是构建评星任务的传统做法。由os.fork创建子进程。
4、由fork和exec组合使用可以运行一个全新的程序。
5、exec共有八种调用形式。os.execv,os.execl,os.execlp,os.execvp,os.execle,os.execve,os.execvpe,os.execlpe。
6、除了fork和exec组合可以启动程序,我们还能使用os.system、os.popen调用、subprocesses模块os.spawnv调用、multiprocessing模块的进程派生模型。
7、和进程相比,线程的好处有:性能改善、简单易用、共享全局内存、可移植性。
8、线程本身是调用函数的。我们必须对线程的多种操作的同步化小心处理。python提供了一个全局锁的概念,个人感觉就是一个全局的Bool变量。python实现现成的优势主要在于性能,如果将虚拟机改造成完全线程安全的,那么在windows下会慢两倍,Linux下更甚。
9、_thread模块和threading模块是python标准库带的两个线程模块,_thread是较低层面的基本接口,threading是基于对象和类的较高层面的接口。
10、queue模块,提供一个标准的队列数据结构——一个先进先出的Python对象的列表。就是一个普通的队列嘛。
11、关于全局解释器锁机制,他可以确保任意给定的时间点最多只有一个线程在python解释器中运行代码。此外,它还通过一些机制确保了每个线程都有机会运行。
12、Python包含C语言工具,可用来将长时运行操作封装在C编码的扩展中,并允许其他Python语言线程并行运行。
------------------------下------------------
13、程序退出。可以使用sys模块,sys.exit(N)。可以使用os模块,os._exit(N)。
14、os.system和os.Popen可以获得退出状态,即N。获得后一般需要进行位操作才能得到我们想要的N。subprocess模块也可以且有多种方法。
15、进程间通信方式有很多种。
16、通信1:匿名管道,类似于共享的内存缓冲,使用正常的python文件调用的方法来处理。用两根管道就可以进行双向IPC(进程间通信Inter-Process Communication)。
17、通信2:FIFO(命名管道),感觉像是队列。区别于匿名管道,它是一个真实的文件,所以可以他们可以用作线程、进程及独立启动的程序间的IPC机制。
18、通信3:套接字,这是老朋友,一个服务端一个客户端,互相通信。十二章会具体讲SOCKET。看见socket实在太亲切。
19、通信4:信号。信号根据编号来识别,而非堆栈。是Python解释器作用域之外的、受控于操作系统的非同步事件机制。
20、通信5:multiprocessing模块,这个最厉害。支持跨平台可移植性、在多核或多CPU机器上真正地并行运行任务。反面的是:1、线程中的共享可变状态不能使用,2、如果使用了不能pickle的对象,那么实现起来会复杂。
21、multiprocessing模块的pipe对象提供了一个可连接两个进程的匿名管道。
22、multiprocessing模块的Value和Array对象实现共享的进程/线程安全的内存以用于进程间通信。
23、multiprocessing模块的Queued对象可用作Python对象的一个先进先出的列表。
24、因为multiprocessing模块的手段,所以其实最长用的是它,因为这些功能更表层(远离底层)。
25、multiprocessing模块的总结:它提供了一个替代方案,这个方案旨在将线程的可移植性和众多便利与进程的完全并行的潜能结合起来,为IPC,推出状态和其他并行处理目标提供多种额外的解决方案。
26、os.spawn函数家族。os.spawnv和os.spawnve调用的出现是为了在windows下启动程序,与类Unix系统中的fork/exec组合很想。
27、还有各种启动程序的方式。这本书提供了一个python程序,是一个跨平台的程序启动框架。我虽然手打了一份,但我还是把附件的内容贴出来吧,毕竟有注释。
1 """
2 ###################################################################################
3 launch Python programs with command lines and reusable launcher scheme classes;
4 auto inserts "python" and/or path to Python executable at front of command line;
5 some of this module may assume 'python' is on your system path (see Launcher.py);
6
7 subprocess module would work too, but os.popen() uses it internally, and the goal
8 is to start a program running independently here, not to connect to its streams;
9 multiprocessing module also is an option, but this is command-lines, not functions:
10 doesn't make sense to start a process which would just do one of the options here;
11
12 new in this edition: runs script filename path through normpath() to change any
13 / to \ for Windows tools where required; fix is inherited by PyEdit and others;
14 on Windows, / is generally allowed for file opens, but not by all launcher tools;
15 ###################################################################################
16 """
17
18 import sys, os
19 pyfile = (sys.platform[:3] == 'win' and 'python.exe') or 'python'
20 pypath = sys.executable # use sys in newer pys
21
22 def fixWindowsPath(cmdline):
23 """
24 change all / to \ in script filename path at front of cmdline;
25 used only by classes which run tools that require this on Windows;
26 on other platforms, this does not hurt (e.g., os.system on Unix);
27 """
28 splitline = cmdline.lstrip().split(' ') # split on spaces
29 fixedpath = os.path.normpath(splitline[0]) # fix forward slashes
30 return ' '.join([fixedpath] + splitline[1:]) # put it back together
31
32 class LaunchMode:
33 """
34 on call to instance, announce label and run command;
35 subclasses format command lines as required in run();
36 command should begin with name of the Python script
37 file to run, and not with "python" or its full path;
38 """
39 def __init__(self, label, command):
40 self.what = label
41 self.where = command
42 def __call__(self): # on call, ex: button press callback
43 self.announce(self.what)
44 self.run(self.where) # subclasses must define run()
45 def announce(self, text): # subclasses may redefine announce()
46 print(text) # methods instead of if/elif logic
47 def run(self, cmdline):
48 assert False, 'run must be defined'
49
50 class System(LaunchMode):
51 """
52 run Python script named in shell command line
53 caveat: may block caller, unless & added on Unix
54 """
55 def run(self, cmdline):
56 cmdline = fixWindowsPath(cmdline)
57 os.system('%s %s' % (pypath, cmdline))
58
59 class Popen(LaunchMode):
60 """
61 run shell command line in a new process
62 caveat: may block caller, since pipe closed too soon
63 """
64 def run(self, cmdline):
65 cmdline = fixWindowsPath(cmdline)
66 os.popen(pypath + ' ' + cmdline) # assume nothing to be read
67
68 class Fork(LaunchMode):
69 """
70 run command in explicitly created new process
71 for Unix-like systems only, including cygwin
72 """
73 def run(self, cmdline):
74 assert hasattr(os, 'fork')
75 cmdline = cmdline.split() # convert string to list
76 if os.fork() == 0: # start new child process
77 os.execvp(pypath, [pyfile] + cmdline) # run new program in child
78
79 class Start(LaunchMode):
80 """
81 run command independent of caller
82 for Windows only: uses filename associations
83 """
84 def run(self, cmdline):
85 assert sys.platform[:3] == 'win'
86 cmdline = fixWindowsPath(cmdline)
87 os.startfile(cmdline)
88
89 class StartArgs(LaunchMode):
90 """
91 for Windows only: args may require real start
92 forward slashes are okay here
93 """
94 def run(self, cmdline):
95 assert sys.platform[:3] == 'win'
96 os.system('start ' + cmdline) # may create pop-up window
97
98 class Spawn(LaunchMode):
99 """
100 run python in new process independent of caller
101 for Windows or Unix; use P_NOWAIT for dos box;
102 forward slashes are okay here
103 """
104 def run(self, cmdline):
105 os.spawnv(os.P_DETACH, pypath, (pyfile, cmdline))
106
107 class Top_level(LaunchMode):
108 """
109 run in new window, same process
110 tbd: requires GUI class info too
111 """
112 def run(self, cmdline):
113 assert False, 'Sorry - mode not yet implemented'
114
115 #
116 # pick a "best" launcher for this platform
117 # may need to specialize the choice elsewhere
118 #
119
120 if sys.platform[:3] == 'win':
121 PortableLauncher = Spawn
122 else:
123 PortableLauncher = Fork
124
125 class QuietPortableLauncher(PortableLauncher):
126 def announce(self, text):
127 pass
128
129 def selftest():
130 file = 'echo.py'
131 input('default mode...')
132 launcher = PortableLauncher(file, file)
133 launcher() # no block
134
135 input('system mode...')
136 System(file, file)() # blocks
137
138 if sys.platform[:3] == 'win':
139 input('DOS start mode...') # no block
140 StartArgs(file, file)()
141
142 if __name__ == '__main__': selftest()