我想你誤會;由於PyMongo的文檔警告你,單個MongoClient不是fork-safe,你可以解釋爲PyMongo禁止你的整個程序創建子進程。
任何單個MongoClient不是叉安全的,這意味着你不能分叉之前創建它,分叉後,使用相同的MongoClient對象。總體來說,在程序中使用PyMongo,或者在分叉之前使用一個MongoClient,而在之後使用不同的MongoClient都是安全的。
這就是爲什麼subprocess.Popen
沒問題:你分叉,然後執行exec(用子進程中的另一個代替你的程序),因此你不可能在子進程中使用同一個MongoClient。
引述PyMongo FAQ:
在Unix系統的多處理模塊使用叉產生進程()。在fork()中使用MongoClient實例時必須小心。具體來說,MongoClient的實例不能從父進程複製到子進程。相反,父進程和每個子進程必須創建他們自己的MongoClient實例。例如:
# Each process creates its own instance of MongoClient.
def func():
db = pymongo.MongoClient().mydb
# Do something with db.
proc = multiprocessing.Process(target=func)
proc.start()
永遠不要這樣做:MongoClient的
client = pymongo.MongoClient()
# Each child process attempts to copy a global MongoClient
# created in the parent process. Never do this.
def func():
db = client.mydb
# Do something with db.
proc = multiprocessing.Process(target=func)
proc.start()
實例從父進程複製具有僵局的子進程中的高概率,由於固有的fork(),線程和鎖之間的不兼容性。如果發生這種死鎖,PyMongo會嘗試發出警告。
啊哈有道理,我也很好奇在子進程中繼承文件描述符(特別是套接字句柄)的潛在副作用,但我猜Popen的close_fds參數地址也是 – nonagon
PyMongo使用FD_CLOEXEC創建其套接字,因此無論您是否傳遞close_fds,這些描述符都會關閉。 –