我有一个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. 在文本文件中打印最后几行
- 6. 在最后一行打印文字“执行;” - 行总是不同的数量
- 7. php script.php打印脚本,而不是在linux上执行它?
- 8. Bash脚本得到打印,而不是被执行
- 9. 完成sge作业后运行脚本
- 10. PHP脚本只能在文件的最后一行
- 11. 在Linux下打印最后5行文件在C中使用
- 12. cron会执行php文件还是只执行CGI脚本?
- 13. 打印只在最后的foreach
- 14. 打印出文件的最后10行
- 15. 在我的python脚本执行后打印这个数字是什么
- 16. HashMap打印只是最后一项
- 17. perl数组只打印最后一行
- 18. TCPDF只打印最后一行
- 19. Bash脚本:从文件打印grep'd行
- 20. BufferedWriter只打印文件的最后一行?
- 21. 页脚在最后打印页MPDF
- 22. 打印文件 - Shell脚本
- 23. 如何在Qt中打印文本文件到打印机?
- 24. 在文本文件中搜索值然后打印下一行
- 25. 打印到Pdf ...只有最后2页
- 26. VBS打印机脚本执行错误
- 27. 打印php脚本输出到文件
- 28. 将python脚本打印到文件
- 29. 在文件中打印最后n-2行的优雅方式
- 30. .vbs脚本在执行过程中在记事本中被打开
谢谢!没有意识到这与Python有什么关系。也发现这篇文章有帮助http://stackoverflow.com/questions/107705/python-output-buffering – miz 2012-03-26 18:12:23