簡體   English   中英

subprocess stderr vs sys.stderr

[英]subprocess stderr vs sys.stderr

我不確定這個問題是Python還是shell問題。

我有一個Python程序,它對命令使用子進程調用,該命令可以在stderr上發出錯誤消息。 我自己的程序也使用sys.stderr來記錄錯誤。 這是一個簡單的例子,命令(ls * .foobar)失敗:

import sys,subprocess

sys.stderr.write("--Hello\n")
try:
    subprocess.check_call("ls *.foobar",shell=True)
except subprocess.CalledProcessError as e:
    sys.stderr.write("Command failed\n")
sys.stderr.write("--Bye\n")

當我運行此代碼時,控制台上的ouptut(來自stderr)如下:

- 你好
ls:無法訪問'* .foobar':沒有這樣的文件或目錄
命令失敗
--Bye

如果我將stderr重定向到文件(例如使用python myscript.py 2> log),該文件包含以下內容:

ls:無法訪問'* .foobar':沒有這樣的文件或目錄
- 你好
命令失敗
--Bye

有沒有辦法保持文件中的消息順序(除了在子進程調用中使用stderr在文件上的顯式重定向)?

這個問題類似於一些標准的stdout / stderr問題,但是,在這里,一切都應該在stderr上。

您需要將數據寫入器刷新stderr描述符:

sys.stderr.write("--Hello\n")
sys.stderr.flush()

當連接到終端時,stdio是行緩沖的,當連接到管道時使用固定緩沖區。 您正在編寫一個\\n換行符,當連接到終端時觸發刷新,但是,如果沒有每行刷新,則在Python退出時,在寫入最終刷新之前,不會寫入足以讓stderr觸發緩沖區刷新。

如果你使用print(..., file=sys.stderr)你可以通過添加flush=True告訴print()發出flush()調用:

print("--Hello", file=sys.stderr, flush=True)

處理此問題的另一種方法是“捕獲並釋放”子進程的stderr輸出:

sys.stderr.write("--Hello\n")
try:
    subprocess.check_call("ls *.foobar", shell=True, stderr=subprocess.PIPE)
except subprocess.CalledProcessError as e:
    sys.stderr.write(e.stderr)
    sys.stderr.write("Command failed\n")
sys.stderr.write("--Bye\n")

stderr=subprocess.PIPE添加告訴subprocess e.stderr捕獲命令的stderr輸出,並且您可以將該輸出作為CalledProcessError異常的e.stderr屬性找到。

暫無
暫無

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

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