《python编程》第五章——并行系统工具(上)

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()

 

posted @ 2017-05-10 22:21  羊头军师  阅读(625)  评论(1编辑  收藏  举报