- 是否有可能捕獲Python腳本Python解釋器的輸出?
- 是否可以從Python腳本中捕獲Windows CMD的輸出?
如果是這樣,我應該看看哪個圖書館(y | ies)?如何從Python腳本捕獲Python解釋器和/或CMD.EXE的輸出?
如果是這樣,我應該看看哪個圖書館(y | ies)?如何從Python腳本捕獲Python解釋器和/或CMD.EXE的輸出?
如果你正在談論的Python解釋器或cmd.exe,這就是你的腳本的「父」,則沒有,這是不可能的。在每一個類似POSIX的系統中(現在你正在運行Windows,看起來,這可能有一些我不知道的怪癖,YMMV),每個進程有三個流,標準輸入,標準輸出和標準錯誤。卜默認這些被定向到控制檯,但重定向可以使用管道符號(在控制檯上運行時):
python script_a.py | python script_b.py
這關係腳本的標準輸出流至腳本B的標準輸入流在這個例子中,標準錯誤仍然在控制檯上。請參閱維基百科上關於standard streams的文章。
如果你在談論一個子進程,你可以從Python啓動它,像這樣(標準輸入也是一種選擇,如果你想雙向通信):
import subprocess
# Of course you can open things other than python here :)
process = subprocess.Popen(["python", "main.py"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
x = process.stderr.readline()
y = process.stdout.readline()
process.wait()
的信息請參見Python的subprocess模塊管理流程。對於通信,process.stdin和process.stdout管道被認爲是標準的file objects。
對於管道的使用,從標準輸入讀爲lassevk建議你做這樣的事情:
import sys
x = sys.stderr.readline()
y = sys.stdin.readline()
sys.stdin和sys.stdout的是標準的文件對象如上所述,在sys定義模塊。您可能還想看看pipes模塊。
用的ReadLine()作爲我的例子中讀數據,雖然獲取數據的一個非常原始的方法。如果輸出不是面向行或不確定的,你可能想看看polling,但不幸的是它不能在Windows中工作,但我確信有一些替代方法。
在哪些方面你問?
你們是不是要捕獲從你在命令行上啓動一個程序的輸出?
如果是這樣,那麼這是如何執行它:
somescript.py | your-capture-program-here
和讀取輸出,從標準輸入剛纔讀。
如果,另一方面,你執行該腳本或cmd.exe,或類似從您的程序中,並要等到腳本/程序已完成,並捕獲所有的輸出,那麼你需要看看你用來啓動外部程序的庫調用,很可能有辦法讓它給你一些方法來讀取輸出並等待完成。
你想subprocess。在17.1.1中特別注意Popen,並在17.1.2中進行交流。
其實,你一定可以,同時它又美又醜又瘋了!
您可以用收集輸出的StringIO對象替換sys.stdout和sys.stderr。
下面是一個例子,它保存爲evil.py:
import sys
import StringIO
s = StringIO.StringIO()
sys.stdout = s
print "hey, this isn't going to stdout at all!"
print "where is it ?"
sys.stderr.write('It actually went to a StringIO object, I will show you now:\n')
sys.stderr.write(s.getvalue())
當你運行這個程序,你會發現:
像這樣替換sys.stdout/err是所謂的monkeypatching的應用程序。無論這種「支持」是什麼,意見可能會有所不同,它絕對是一種醜陋的黑客攻擊,但它在試圖環繞外部事物一次或兩次時拯救了我的培根。
在Linux上進行測試,而不是在Windows上進行測試,但它應該也能正常工作。讓我知道它是否適用於Windows!
我想我可以指出你的問題的第一部分的一個很好的答案。
1. 是否有可能從一個Python腳本 捕捉Python解釋器的輸出?
答案是「是」,並親自我喜歡從PEP 343 -- The "with" Statement文檔中的例子下面舉。
from contextlib import contextmanager
import sys
@contextmanager
def stdout_redirected(new_stdout):
saved_stdout = sys.stdout
sys.stdout = new_stdout
try:
yield None
finally:
sys.stdout.close()
sys.stdout = saved_stdout
而這樣使用的:
with stdout_redirected(open("filename.txt", "w")):
print "Hello world"
它的一個好的方面是,它可以應用於選擇性地圍繞只是一個腳本的執行的一部分,而不是它的整個範圍,並停留在效果即使在其上下文中引發了未處理的異常。如果你第一次使用後,重新打開附加模式的文件,你可以積累的結果到單個文件:
with stdout_redirected(open("filename.txt", "w")):
print "Hello world"
print "screen only output again"
with stdout_redirected(open("filename.txt", "a")):
print "Hello world2"
當然,上述也可以擴展到也重定向sys.stderr
相同或另一個文件。另請參閱此answer相關問題。
請注意,使用subprocess.Popen()調用Python時,傳遞「-u」標誌通常會有幫助,該標誌禁用stdin/stdout/stderr上的緩衝。當孩子開始讀取標準輸入時,如果輸出已被重定向到管道,Python不會自動刷新標準輸出,因此您可以最終阻止永久讀取緩衝的輸出。我遇到了這個問題,試圖包裝/自動化pdb。 – 2011-11-18 16:29:49