Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/334.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python SGE脚本:在执行期间打印到文件(而不仅仅是在最后)?_Python_Qsub_Sungridengine - Fatal编程技术网

Python SGE脚本:在执行期间打印到文件(而不仅仅是在最后)?

Python SGE脚本:在执行期间打印到文件(而不仅仅是在最后)?,python,qsub,sungridengine,Python,Qsub,Sungridengine,我有一个SGE脚本来执行一些python代码,使用qsub提交到队列。在python脚本中,我有几个print语句(更新我的程序进度)。当我从命令行运行python脚本时,print语句被发送到stdout。对于sge脚本,我使用-o选项将输出重定向到文件。但是,似乎只有在python脚本完成运行后,脚本才会将它们发送到文件中。这很烦人,因为(a)我无法再看到程序上的实时更新,(b)如果我的作业没有正确终止(例如,如果我的作业被踢出队列),则不会打印任何更新。如何确保每次打印某个内容时脚本都会写

我有一个SGE脚本来执行一些python代码,使用qsub提交到队列。在python脚本中,我有几个print语句(更新我的程序进度)。当我从命令行运行python脚本时,print语句被发送到stdout。对于sge脚本,我使用-o选项将输出重定向到文件。但是,似乎只有在python脚本完成运行后,脚本才会将它们发送到文件中。这很烦人,因为(a)我无法再看到程序上的实时更新,(b)如果我的作业没有正确终止(例如,如果我的作业被踢出队列),则不会打印任何更新。如何确保每次打印某个内容时脚本都会写入文件,而不是在最后将其全部集中在一起?

我认为您遇到了缓冲输出的问题。Python使用一个库来处理它的输出,并且该库知道在不与tty对话的时候编写一个块更有效

有几种方法可以解决这个问题。您可以使用“-u”选项运行python(有关详细信息,请参阅python手册页),例如,在脚本的第一行中使用如下内容:

#! /usr/bin/python -u
但是,如果您使用“/usr/bin/env”技巧,这将不起作用,因为您不知道python安装在哪里

另一种方法是使用如下内容重新打开stdout:

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执行类似的操作。

我刚刚在SGE中遇到了一个类似的问题,没有“取消缓冲”文件IO似乎对我有效。我必须等到程序执行结束才能看到任何输出

我找到的解决方法是将sys.stdout包装到一个自定义对象中,该对象重新实现“write”方法。这种新方法不是实际写入标准输出,而是打开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()

这是SGE缓冲进程的输出,无论是python进程还是任何其他进程,都会发生这种情况

通常,您可以通过更改和重新编译来减少或禁用SGE中的缓冲。但这并不是一件好事,所有这些数据都将缓慢写入磁盘,从而影响整体性能

这对我很有用:

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)

这个问题与NFS在关闭文件或调用fsync之前不将数据同步回主机有关。

正如其他人提到的,出于性能原因,在未连接到tty时不总是写入标准输出

如果您希望在某个特定点写入标准输出,可以使用

import sys
sys.stdout.flush()

此时。

为什么不打印到文件而不是标准输出

outFileID = open('output.log','w')
print(outFileID,'INFO: still working!')
print(outFileID,'WARNING: blah blah!')
和使用

tail -f output.log

我今天遇到了同样的问题,并通过写入磁盘而不是打印来解决它:

with open('log-file.txt','w') as out:
  out.write(status_report)

谢谢我不知道这和python有什么关系。我也觉得这篇文章很有帮助