[英]Python subprocess.Call() with spaced argument like "-charset FileName=latin"
[英]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=PIPE
或stderr=PIPE
傳遞給subprocess.call
,因此它可能死鎖的事實無關緊要。
傳遞的唯一原因stdout=PIPE
或stderr=PIPE
到subprocess.Popen
是讓你可以使用POPEN實例的stdout
和stderr
的文件對象的屬性。 由於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.