我有一個SGE腳本來執行一些使用qsub提交給隊列的python代碼。在python腳本中,我有幾個打印語句(更新程序的進度)。當我從命令行運行python腳本時,打印語句被髮送到stdout。對於sge腳本,我使用-o選項將輸出重定向到文件。但是,腳本似乎只會在python腳本運行完成後纔將這些文件發送到文件中。這很煩人,因爲(a)我再也看不到程序的實時更新,以及(b)如果我的作業沒有正確終止(例如,如果我的作業從隊列中被踢出),則沒有打印任何更新。我怎樣才能確保每次我要打印文件時腳本都會寫入文件,而不是在最後把所有文件合併在一起?SGE腳本:在執行過程中打印到文件(不只是在最後)?
5
A
回答
5
我認爲你遇到了緩衝輸出的問題。 Python使用一個庫來處理它的輸出,並且庫知道當它不與一個tty交談時編寫一個塊會更高效。
有幾種方法可以解決這個問題。您可以通過「-u」選項(詳見蟒蛇手冊頁)運行python,例如,像這樣的東西作爲腳本的第一行:
#! /usr/bin/python -u
但是,這並不工作,如果你正在使用「/ usr/bin/env」技巧,因爲你不知道python的安裝位置。
另一種方式是像這樣的東西重新打開標準輸出:
import sys
import os
# reopen stdout file descriptor with write mode
# and 0 as the buffer size (unbuffered)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)
注os.fdopen的bufsize參數被設置爲0,迫使它是緩衝。你可以用sys.stderr做類似的事情。
3
我剛剛遇到了與SGE類似的問題,沒有suggested method來「緩衝」文件IO似乎爲我工作。我必須等到程序執行結束才能看到任何輸出。
我發現的解決方法是將sys.stdout包裝到重新實現「寫入」方法的自定義對象中。這種新方法不是實際寫入標準輸出,而是打開IO重定向的文件,追加所需數據,然後關閉文件。這有點難看,但我發現它解決了這個問題,因爲文件的實際打開/關閉迫使IO交互。
這裏有一個小例子:
import os, sys, time
class RedirIOStream:
def __init__(self, stream, REDIRPATH):
self.stream = stream
self.path = REDIRPATH
def write(self, data):
# instead of actually writing, just append to file directly!
myfile = open(self.path, 'a')
myfile.write(data)
myfile.close()
def __getattr__(self, attr):
return getattr(self.stream, attr)
if not sys.stdout.isatty():
# Detect redirected stdout and std error file locations!
# Warning: this will only work on LINUX machines
STDOUTPATH = os.readlink('/proc/%d/fd/1' % os.getpid())
STDERRPATH = os.readlink('/proc/%d/fd/2' % os.getpid())
sys.stdout=RedirIOStream(sys.stdout, STDOUTPATH)
sys.stderr=RedirIOStream(sys.stderr, STDERRPATH)
# Simple program to print msg every 3 seconds
def main():
tstart = time.time()
for x in xrange(10):
time.sleep(3)
MSG = ' %d/%d after %.0f sec' % (x, args.nMsg, time.time()-tstart)
print MSG
if __name__ == '__main__':
main()
3
這是上海黃金交易所的緩衝過程的輸出,它是否發生了一個Python程序或任何其他。
一般而言,您可以通過更改並重新編譯來減少或禁用SGE中的緩衝。但它不是一件好事,所有這些數據將會慢慢寫入磁盤,影響你的整體性能。
0
這個工作對我來說:
class ForceIOStream:
def __init__(self, stream):
self.stream = stream
def write(self, data):
self.stream.write(data)
self.stream.flush()
if not self.stream.isatty():
os.fsync(self.stream.fileno())
def __getattr__(self, attr):
return getattr(self.stream, attr)
sys.stdout = ForceIOStream(sys.stdout)
sys.stderr = ForceIOStream(sys.stderr)
和問題有,直到文件被關閉或FSYNC被稱爲NFS不是主數據同步回做。
4
正如其他人所提到的,當沒有連接到tty時,出於性能原因不總是編寫stdout。
如果你有要被寫入標準輸出一個特定的點,你可以強制使用
import sys
sys.stdout.flush()
在這一點上。
0
爲什麼不打印到文件而不是標準輸出?
outFileID = open('output.log','w')
print(outFileID,'INFO: still working!')
print(outFileID,'WARNING: blah blah!')
,並使用
tail -f output.log
0
我今天打這個同樣的問題,僅通過寫磁盤,而不是印刷解決它:
with open('log-file.txt','w') as out:
out.write(status_report)
相關問題
- 1. Shell腳本在上次執行後修改後打印文件?
- 2. 只打印文件的最後一行?
- 3. 運行python腳本而不在最後打印換行符?
- 4. 如何通過僅在最後打開文件來在不同執行點的文件中打印時間?
- 5. Bash腳本得到打印,而不是被執行
- 6. 完成sge作業後運行腳本
- 7. 在Linux下打印最後5行文件在C中使用
- 8. cron會執行php文件還是隻執行CGI腳本?
- 9. 打印出文件的最後10行
- 10. Bash腳本:從文件打印grep'd行
- 11. HashMap打印只是最後一項
- 12. BufferedWriter只打印文件的最後一行?
- 13. 如何在Qt中打印文本文件到打印機?
- 14. 將python腳本打印到文件
- 15. 打印php腳本輸出到文件
- 16. 在文件中打印最後n-2行的優雅方式
- 17. iOS - 在uiwebview中將文本打印爲不執行
- 18. .vbs腳本在執行過程中在記事本中被打開
- 19. 確定腳本是否在SGE中運行
- 20. Webdriver腳本不會打印到文本文件
- 21. 在serializeFileUpload後執行腳本
- 22. 在bash腳本中執行jar文件
- 23. 批處理腳本打印將被執行的命令,而不是執行
- 24. 在腳本中操作並打印到PDF文件
- 25. 調度程序執行批處理腳本10行後的打印行
- 26. Python腳本只在執行後輸出到瀏覽器
- 27. 腳本讀取行,從值中選擇,並打印到文件
- 28. 過程在SQL Developer內部執行,但不在腳本中執行
- 29. shell腳本在執行過程中執行的分支數
- 30. 只有第一行輸出打印到我的文本文件
謝謝!沒有意識到這與Python有什麼關係。也發現這篇文章有幫助http://stackoverflow.com/questions/107705/python-output-buffering – miz 2012-03-26 18:12:23