簡體   English   中英

為什么python的subprocess.call是這樣實現的?

[英]Why is python's subprocess.call implemented like this?

子進程模塊具有便捷函數call ,在2.6和3.1中都是這樣實現的:

def call(*popenargs, **kwargs):
    return Popen(*popenargs, **kwargs).wait()

該功能的文檔帶有紅色警告,閱讀:

警告 :與Popen.wait() ,當使用stdout=PIPE和/或stderr=PIPE時,這會死鎖,子進程會為管道生成足夠的輸出,以阻止等待OS管道緩沖區接受更多數據。

Popen.wait()文檔說在這種情況下使用Popen.communicate() 那么,為什么不call只是像下面這樣實現,所以可以刪除愚蠢的警告,並從標准庫中刪除這樣的愚蠢限制?

def call(*args, **kwargs):
    input = kwargs.pop("input", None)
    p = Popen(*args, **kwargs)
    p.communicate(input)
    return p.returncode

我確定這是有原因的。 我錯過了什么?

我花了一些時間瀏覽PEP-324 ,它介紹了子過程模塊,試圖弄清楚所涉及的設計決策,但我認為答案實際上非常簡單:

沒有理由stdout=PIPEstderr=PIPE傳遞給subprocess.call ,因此它可能死鎖的事實無關緊要。

傳遞的唯一原因stdout=PIPEstderr=PIPEsubprocess.Popen是讓你可以使用POPEN實例的stdoutstderr的文件對象的屬性。 由於subprocess.call永遠不會讓您看到Popen實例,因此PIPE選項變得無關緊要。

Popen.communicate有潛在的開銷(通過監視管道創建額外的線程以避免死鎖),在這種情況下沒有任何好處,因此沒有理由使用它。

編輯 :如果你想丟棄你的輸出,我想最好這樣做明確:

# option 1
with open(os.devnull, 'w') as dev_null:
    subprocess.call(['command'], stdout=dev_null, stderr=dev_null)

# option 2
subprocess.call(['command >& /dev/null'], shell=True)

而不是指示子進程將所有輸出捕獲到您從未打算使用的PIPE文件。

如果您只想運行命令並獲取退出狀態以確定它是成功還是失敗,那么您不需要通過管道與它通信。 這是subprocess.call()方法的便利。 子進程模塊中還有其他便利功能,它們以有效的方式封裝了使用Popen對象的許多常見用法。

如果您需要將子進程stdout或stderr傳遞給某個地方,而不是使用call(),請使用Popen對象並與文檔狀態通信()。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM