Concurrent Execution
TL;DR;
- 使用 python 作为引子/driver 启动其他独立进程,使用 exec.
- 使用 python 作为主进程管理,子进程是独立启动的进程,使用 subprocess.Popen.
- 子进程是 python 函数使用 multiprocessing。
- 把 python 函数当作线程启动时使用 threading。
https://docs.python.org/3/library/concurrency.html
1. subprocess
- 启动子进程,自定义 excutable
import subprocess
proc = subprocess.Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])
proc.poll()
proc.wait()
proc.communicate()
proc.terminate()
proc.kill()
https://docs.python.org/3/library/subprocess.html
2. threading
- 启动线程
- 存在 GIL 问题,无法完全利用 CPU
import threading
def serve():
pass
thread = threading.Thread(target=serve, daemon=None)
thread.start()
thread.join()
https://docs.python.org/3/library/threading.html
Pros
- Lightweight - low memory footprint
- Shared memory - makes access to state from another context easier
- Allows you to easily make responsive UIs
- cPython C extension modules that properly release the GIL will run in parallel
- Great option for I/O-bound applications
Cons
- cPython - subject to the GIL
- Not interruptible/killable
- If not following a command queue/message pump model (using the Queue module), then manual use of synchronization primitives become a necessity (decisions are needed for the granularity of locking)
- Code is usually harder to understand and to get right - the potential for race conditions increases dramatically
3. multiprocessing
- 启动子进程,使用内置函数
- 使用进程,充分利用 CPU 资源
from multiprocessing
proc = multiprocessing.Process(target=serve, daemon=None)
proc.start()
proc.join()
proc.close()
https://docs.python.org/3/library/multiprocessing.html
Pros
- Separate memory space
- Code is usually straightforward
- Takes advantage of multiple CPUs & cores
- Avoids GIL limitations for cPython
- Eliminates most needs for synchronization primitives unless if you use shared memory (instead, it's more of a communication model for IPC)
- Child processes are interruptible/killable
- Python multiprocessing module includes useful abstractions with an interface much like threading.Thread
- A must with cPython for CPU-bound processing
Cons
- IPC a little more complicated with more overhead (communication model vs. shared memory/objects)
- Larger memory footprint
4. Executor
https://docs.python.org/3/library/concurrent.futures.html
- ProcessPoolExecutor 封装 multiprocessing module,提供进程池
- ThreadPoolExecutor, 线程池
API
class concurrent.futures.Executor:
submit(fn, /, *args, **kwargs)
map(func, *iterables, timeout=None, chunksize=1)
shutdown(wait=True, *, cancel_futures=False)
调用 submit 返回 concurrent.futures.Future
, 使用 result(timeout=None) 获取结果。.
exec
python 转 shell 执行
os.execve('/bin/sh', 'echo', 'ok')