当前位置: 首页 > 面试题库 >

Python-如何将sys.stdout复制到日志文件?

戴博
2023-03-14
问题内容

编辑:由于似乎没有解决方案,或者我正在做一些人都不知道的非标准操作-我将修订我的问题,并问:当python应用正在制作日志时,完成记录的最佳方法是什么?很多系统调用?

我的应用程序有两种模式。在交互模式下,我希望所有输出都转到屏幕以及日志文件中,包括所有系统调用的输出。在守护程序模式下,所有输出进入日志。守护程序模式使用时效果很好os.dup2()。我找不到在不修改每个系统调用的情况下以交互方式将所有输出“发送”到日志的方法。

换句话说,我想要python应用程序生成的任何输出(包括系统调用output)的命令行“ tee”的功能。

澄清:

要重定向所有输出,我可以执行以下操作,并且效果很好:

# open our log file
so = se = open("%s.log" % self.name, 'w', 0)

# re-open stdout without buffering
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

# redirect stdout and stderr to the log file opened above
os.dup2(so.fileno(), sys.stdout.fileno())
os.dup2(se.fileno(), sys.stderr.fileno())

这样做的好处是,不需要其余代码即可进行特殊的打印调用。该代码还运行一些shell命令,因此不必分别处理它们的每个输出也很不错。

简而言之,除了复制而不是重定向外,我想做同样的事情。

乍一想,我认为简单地反转即可dup2。为什么不呢?这是我的测试:

import os, sys

### my broken solution:
so = se = open("a.log", 'w', 0)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

os.dup2(sys.stdout.fileno(), so.fileno())
os.dup2(sys.stderr.fileno(), se.fileno())
###

print("foo bar")

os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)

文件“ a.log”应与屏幕上显示的相同。


问题答案:

由于你很习惯从代码中生成外部进程,因此可以使用tee它本身。我不知道有什么Unix系统调用可以完全做到这tee一点。

# Note this version was written circa Python 2.6, see below for
# an updated 3.3+-compatible version.
import subprocess, os, sys

# Unbuffer output (this ensures the output is in the correct order)
sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 0)

tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())

print "\nstdout"
print >>sys.stderr, "stderr"
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)

你还可以tee使用多处理程序包进行仿真(如果使用的是Python 2.5或更早版本,则可以使用处理程序)。

更新资料

这是与Python 3.3+兼容的版本:

import subprocess, os, sys

tee = subprocess.Popen(["tee", "log.txt"], stdin=subprocess.PIPE)
# Cause tee's stdin to get a copy of our stdin/stdout (as well as that
# of any child processes we spawn)
os.dup2(tee.stdin.fileno(), sys.stdout.fileno())
os.dup2(tee.stdin.fileno(), sys.stderr.fileno())

# The flush flag is needed to guarantee these lines are written before
# the two spawned /bin/ls processes emit any output
print("\nstdout", flush=True)
print("stderr", file=sys.stderr, flush=True)

# These child processes' stdin/stdout are 
os.spawnve("P_WAIT", "/bin/ls", ["/bin/ls"], {})
os.execve("/bin/ls", ["/bin/ls"], os.environ)


 类似资料:
  • 问题内容: 我想及时重定向过程的输出。如果我等待过程完成,我可以这样做: 但是,如果该过程花费很长时间或没有完成,则将没有太大用处。我知道我可以像这样实时写入stdout: 但是,这实际上并没有帮助我,因为我正在编写未写入终端的服务。我正在寻找可以让我做类似的事情: 不能直接访问其作者,因此这是不可能的。当然,我不是唯一遇到这个问题的人,这通常是怎么做的? 问题答案: 您应该在此处使用管道,例如:

  • 问题内容: 我正在使用Windows 7和python 2.7。我想将日志文件大小限制为5MB。我的应用程序启动后会写入日志文件,然后该应用程序终止。当我的应用再次启动时,它将写入同一日志文件。因此应用无法持续运行。应用程序启动,处理和终止。 我的记录代码是: 我尝试过 RotatingFileHandler, 但是没有用 那么,如何在python中实施文件大小限制? 问题答案: 丢失并使用Rot

  • 问题内容: 此代码是否同时写入日志文件和控制台? 问题答案: 不,它不会同时写入两者。只会写入控制台。关于原始代码的简短说明。我想您在某处定义,但是代码仍然不正确。您需要在语句中使用引号,例如: 因为我认为您是要附加到文件中。否则,您的代码将抛出一个因为未定义的变量。 但是,正如其他人所说,您应该强烈考虑使用日志记录模块。这是一个如何同时写入控制台和日志文件的简单示例。该代码部分源自此处和此处:

  • 问题内容: 我正在尝试使用Go写入日志文件。 我尝试了几种方法,但都失败了。这是我尝试过的: 日志文件被创建,但是没有任何打印或附加到该文件。为什么? 问题答案: 过去的工作方式一定不同,但这对我有用: 基于Go文档,不能用于,因为它会打开文件“供阅读:” 打开命名文件以供读取。如果成功,则可以使用返回文件上的方法进行读取;关联的文件描述符具有mode 。如果有错误,它将是类型。 编辑 检查后移至

  • 我正在尝试在我的本地机器上启动一个hadoop单节点集群。我已经根据https://amodernstory.com/2014/09/23/installing-hadoop-on-mac-osx-yosemite/配置了以下文件:hadoop-env.sh、core-site.xml、mapred-site.xml和hdfs-site.xml。当我运行脚本和命令(在运行之后)时,我看到数据阳极已

  • 我想在日志文件中看到我的jnlp标准输出。请建议。p. s.我jnlp在windows下运行,使用log4j记录器