《python編程》第五章——並行系統工具(上)

一、同時運行多個任務有兩種基本作法:進程分支和線程派生。python

二、windows下的Python標準版不支持進程分支。shell

三、分支的進程是構建評星任務的傳統作法。由os.fork建立子進程。windows

四、由fork和exec組合使用能夠運行一個全新的程序。安全

五、exec共有八種調用形式。os.execv,os.execl,os.execlp,os.execvp,os.execle,os.execve,os.execvpe,os.execlpe。數據結構

六、除了fork和exec組合能夠啓動程序,咱們還能使用os.system、os.popen調用、subprocesses模塊os.spawnv調用、multiprocessing模塊的進程派生模型。框架

七、和進程相比,線程的好處有:性能改善、簡單易用、共享全局內存、可移植性。less

八、線程自己是調用函數的。咱們必須對線程的多種操做的同步化當心處理。python提供了一個全局鎖的概念,我的感受就是一個全局的Bool變量。python實現現成的優點主要在於性能,若是將虛擬機改形成徹底線程安全的,那麼在windows下會慢兩倍,Linux下更甚。socket

九、_thread模塊和threading模塊是python標準庫帶的兩個線程模塊,_thread是較低層面的基本接口,threading是基於對象和類的較高層面的接口。函數

十、queue模塊,提供一個標準的隊列數據結構——一個先進先出的Python對象的列表。就是一個普通的隊列嘛。工具

十一、關於全局解釋器鎖機制,他能夠確保任意給定的時間點最多隻有一個線程在python解釋器中運行代碼。此外,它還經過一些機制確保了每一個線程都有機會運行。

十二、Python包含C語言工具,可用來將長時運行操做封裝在C編碼的擴展中,並容許其餘Python語言線程並行運行。

------------------------下------------------

1三、程序退出。可使用sys模塊,sys.exit(N)。可使用os模塊,os._exit(N)。

1四、os.system和os.Popen能夠得到退出狀態,即N。得到後通常須要進行位操做才能獲得咱們想要的N。subprocess模塊也能夠且有多種方法。

1五、進程間通訊方式有不少種。

1六、通訊1:匿名管道,相似於共享的內存緩衝,使用正常的python文件調用的方法來處理。用兩根管道就能夠進行雙向IPC(進程間通訊Inter-Process Communication)。

1七、通訊2:FIFO(命名管道),感受像是隊列。區別於匿名管道,它是一個真實的文件,因此能夠他們能夠用做線程、進程及獨立啓動的程序間的IPC機制。

1八、通訊3:套接字,這是老朋友,一個服務端一個客戶端,互相通訊。十二章會具體講SOCKET。看見socket實在太親切。

1九、通訊4:信號。信號根據編號來識別,而非堆棧。是Python解釋器做用域以外的、受控於操做系統的非同步事件機制。

20、通訊5:multiprocessing模塊,這個最厲害。支持跨平臺可移植性、在多核或多CPU機器上真正地並行運行任務。反面的是:一、線程中的共享可變狀態不能使用,二、若是使用了不能pickle的對象,那麼實現起來會複雜。

2一、multiprocessing模塊的pipe對象提供了一個可鏈接兩個進程的匿名管道。

2二、multiprocessing模塊的Value和Array對象實現共享的進程/線程安全的內存以用於進程間通訊。

2三、multiprocessing模塊的Queued對象可用做Python對象的一個先進先出的列表。

2四、由於multiprocessing模塊的手段,因此其實最長用的是它,由於這些功能更表層(遠離底層)。

2五、multiprocessing模塊的總結:它提供了一個替代方案,這個方案旨在將線程的可移植性和衆多便利與進程的徹底並行的潛能結合起來,爲IPC,推出狀態和其餘並行處理目標提供多種額外的解決方案。

2六、os.spawn函數家族。os.spawnv和os.spawnve調用的出現是爲了在windows下啓動程序,與類Unix系統中的fork/exec組合很想。

2七、還有各類啓動程序的方式。這本書提供了一個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()
相關文章
相關標籤/搜索