本文翻译自:Redirect stdout to a file in Python?

How do I redirect stdout to an arbitrary file in Python? 如何在Python中将stdout重定向到任意文件?

When a long-running Python script (eg, web application) is started from within the ssh session and backgounded, and the ssh session is closed, the application will raise IOError and fail the moment it tries to write to stdout. 当从ssh会话中启动运行了长时间的Python脚本(例如,Web应用程序)并进行背景调整,并且ssh会话关闭时,该应用程序将在尝试写入stdout时引发IOError并失败。 I needed to find a way to make the application and modules output to a file rather than stdout to prevent failure due to IOError. 我需要找到一种方法来使应用程序和模块输出到文件而不是stdout,以防止由于IOError而导致失败。 Currently, I employ nohup to redirect output to a file, and that gets the job done, but I was wondering if there was a way to do it without using nohup, out of curiosity. 当前,我使用nohup将输出重定向到文件,并且可以完成工作,但是我想知道是否有一种出于好奇而无需使用nohup的方法。

I have already tried sys.stdout = open('somefile', 'w') , but this does not seem to prevent some external modules from still outputting to terminal (or maybe the sys.stdout = ... line did not fire at all). 我已经尝试过sys.stdout = open('somefile', 'w') ,但这似乎并不能阻止某些外部模块仍然输出到终端(或者sys.stdout = ...行未在所有)。 I know it should work from simpler scripts I've tested on, but I also didn't have time yet to test on a web application yet. 我知道它应该可以通过我测试过的简单脚本工作,但是我还没有时间在Web应用程序上进行测试。


#1楼

参考:https://stackoom.com/question/jCmY/将stdout重定向到Python中的文件


#2楼

The other answers didn't cover the case where you want forked processes to share your new stdout. 其他答案没有涉及您希望分叉的进程共享新标准输出的情况。

To do that: 要做到这一点:

from os import open, close, dup, O_WRONLYold = dup(1)
close(1)
open("file", O_WRONLY) # should open on 1..... do stuff and then restoreclose(1)
dup(old) # should dup to 1
close(old) # get rid of left overs

#3楼

Quoted from PEP 343 -- The "with" Statement (added import statement): 引用自PEP 343-“ with”语句 (添加的导入语句):

Redirect stdout temporarily: 暂时重定向标准输出:

import sys
from contextlib import contextmanager
@contextmanager
def stdout_redirected(new_stdout):save_stdout = sys.stdoutsys.stdout = new_stdouttry:yield Nonefinally:sys.stdout = save_stdout

Used as follows: 用法如下:

with open(filename, "w") as f:with stdout_redirected(f):print "Hello world"

This isn't thread-safe, of course, but neither is doing this same dance manually. 当然,这不是线程安全的,但是也没有手动进行相同的舞蹈。 In single-threaded programs (for example in scripts) it is a popular way of doing things. 在单线程程序中(例如在脚本中),这是一种流行的处理方式。


#4楼

Programs written in other languages (eg C) have to do special magic (called double-forking) expressly to detach from the terminal (and to prevent zombie processes). 用其他语言(例如C)编写的程序必须做特别的魔术(称为双叉)才能与终端分离(并防止僵尸进程)。 So, I think the best solution is to emulate them. 因此,我认为最好的解决方案是模仿它们。

A plus of re-executing your program is, you can choose redirections on the command-line, eg /usr/bin/python mycoolscript.py 2>&1 1>/dev/null 重新执行程序的一个/usr/bin/python mycoolscript.py 2>&1 1>/dev/null是,您可以在命令行上选择重定向,例如/usr/bin/python mycoolscript.py 2>&1 1>/dev/null

See this post for more info: What is the reason for performing a double fork when creating a daemon? 有关更多信息,请参见此帖子: 创建守护程序时执行双叉的原因是什么?


#5楼

There is contextlib.redirect_stdout() function in Python 3.4: Python 3.4中有contextlib.redirect_stdout()函数 :

from contextlib import redirect_stdoutwith open('help.txt', 'w') as f:with redirect_stdout(f):print('it now prints to `help.text`')

It is similar to: 它类似于:

import sys
from contextlib import contextmanager@contextmanager
def redirect_stdout(new_target):old_target, sys.stdout = sys.stdout, new_target # replace sys.stdouttry:yield new_target # run some code with the replaced stdoutfinally:sys.stdout = old_target # restore to the previous value

that can be used on earlier Python versions. 可以在早期的Python版本中使用。 The latter version is not reusable . 后一版本不可重用 。 It can be made one if desired. 如果需要,可以将其制成一个。

It doesn't redirect the stdout at the file descriptors level eg: 它不会在文件描述符级别重定向标准输出,例如:

import os
from contextlib import redirect_stdoutstdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, redirect_stdout(f):print('redirected to a file')os.write(stdout_fd, b'not redirected')os.system('echo this also is not redirected')

b'not redirected' and 'echo this also is not redirected' are not redirected to the output.txt file. b'not redirected''echo this also is not redirected'未重定向到output.txt文件。

To redirect at the file descriptor level, os.dup2() could be used: 要在文件描述符级别重定向,可以使用os.dup2()

import os
import sys
from contextlib import contextmanagerdef fileno(file_or_fd):fd = getattr(file_or_fd, 'fileno', lambda: file_or_fd)()if not isinstance(fd, int):raise ValueError("Expected a file (`.fileno()`) or a file descriptor")return fd@contextmanager
def stdout_redirected(to=os.devnull, stdout=None):if stdout is None:stdout = sys.stdoutstdout_fd = fileno(stdout)# copy stdout_fd before it is overwritten#NOTE: `copied` is inheritable on Windows when duplicating a standard streamwith os.fdopen(os.dup(stdout_fd), 'wb') as copied: stdout.flush()  # flush library buffers that dup2 knows nothing abouttry:os.dup2(fileno(to), stdout_fd)  # $ exec >&toexcept ValueError:  # filenamewith open(to, 'wb') as to_file:os.dup2(to_file.fileno(), stdout_fd)  # $ exec > totry:yield stdout # allow code to be run with the redirected stdoutfinally:# restore stdout to its previous value#NOTE: dup2 makes stdout_fd inheritable unconditionallystdout.flush()os.dup2(copied.fileno(), stdout_fd)  # $ exec >&copied

The same example works now if stdout_redirected() is used instead of redirect_stdout() : 如果使用stdout_redirected()而不是redirect_stdout()则现在可以使用相同的示例:

import os
import sysstdout_fd = sys.stdout.fileno()
with open('output.txt', 'w') as f, stdout_redirected(f):print('redirected to a file')os.write(stdout_fd, b'it is redirected now\n')os.system('echo this is also redirected')
print('this is goes back to stdout')

The output that previously was printed on stdout now goes to output.txt as long as stdout_redirected() context manager is active. 只要上下文管理器stdout_redirected()处于活动状态,以前打印在stdout上的输出现在将进入output.txt

Note: stdout.flush() does not flush C stdio buffers on Python 3 where I/O is implemented directly on read() / write() system calls. 注意: stdout.flush()不会刷新Python 3上的C stdio缓冲区,在该Python 3上,I / O是直接在read() / write()系统调用上实现的。 To flush all open C stdio output streams, you could call libc.fflush(None) explicitly if some C extension uses stdio-based I/O: 要刷新所有打开的C stdio输出流,如果某些C扩展使用基于stdio的I / O,则可以显式调用libc.fflush(None)

try:import ctypesfrom ctypes.util import find_library
except ImportError:libc = None
else:try:libc = ctypes.cdll.msvcrt # Windowsexcept OSError:libc = ctypes.cdll.LoadLibrary(find_library('c'))def flush(stream):try:libc.fflush(None)stream.flush()except (AttributeError, ValueError, IOError):pass # unsupported

You could use stdout parameter to redirect other streams, not only sys.stdout eg, to merge sys.stderr and sys.stdout : 您可以使用stdout参数重定向其他流,而不仅仅是sys.stdout例如,合并sys.stderrsys.stdout

def merged_stderr_stdout():  # $ exec 2>&1return stdout_redirected(to=sys.stdout, stdout=sys.stderr)

Example: 例:

from __future__ import print_function
import syswith merged_stderr_stdout():print('this is printed on stdout')print('this is also printed on stdout', file=sys.stderr)

Note: stdout_redirected() mixes buffered I/O ( sys.stdout usually) and unbuffered I/O (operations on file descriptors directly). 注意: stdout_redirected()将缓冲的I / O(通常为sys.stdout )和无缓冲的I / O(直接对文件描述符的操作)混合使用。 Beware, there could be buffering issues . 当心,可能存在缓冲 问题 。

To answer, your edit: you could use python-daemon to daemonize your script and use logging module (as @erikb85 suggested ) instead of print statements and merely redirecting stdout for your long-running Python script that you run using nohup now. 要回答,请进行编辑:您可以使用python-daemon并使用logging模块(如@ erikb85建议 )代替print语句,而仅将stdout重定向为您现在使用nohup运行的长期运行的Python脚本。


#6楼

Based on this answer: https://stackoverflow.com/a/5916874/1060344 , here is another way I figured out which I use in one of my projects. 基于以下答案: https : //stackoverflow.com/a/5916874/1060344 ,这是我想出在我的一个项目中使用的另一种方法。 For whatever you replace sys.stderr or sys.stdout with, you have to make sure that the replacement complies with file interface, especially if this is something you are doing because stderr/stdout are used in some other library that is not under your control. 对于用sys.stderrsys.stdout替换的任何内容,都必须确保替换符合file接口,尤其是在执行此操作时,因为stderr / stdout用于其他不受您控制的库中。 That library may be using other methods of file object. 该库可能正在使用文件对象的其他方法。

Check out this way where I still let everything go do stderr/stdout (or any file for that matter) and also send the message to a log file using Python's logging facility (but you can really do anything with this): 看看这种方式,我仍然可以让所有事情继续进行stderr / stdout(或与此有关的任何文件),并使用Python的日志记录工具将消息发送到日志文件中(但您实际上可以执行任何操作):

class FileToLogInterface(file):'''Interface to make sure that everytime anything is written to stderr, it isalso forwarded to a file.'''def __init__(self, *args, **kwargs):if 'cfg' not in kwargs:raise TypeError('argument cfg is required.')else:if not isinstance(kwargs['cfg'], config.Config):raise TypeError('argument cfg should be a valid ''PostSegmentation configuration object i.e. ''postsegmentation.config.Config')self._cfg = kwargs['cfg']kwargs.pop('cfg')self._logger = logging.getlogger('access_log')super(FileToLogInterface, self).__init__(*args, **kwargs)def write(self, msg):super(FileToLogInterface, self).write(msg)self._logger.info(msg)

将stdout重定向到Python中的文件?相关推荐

  1. python stdout_将stdout重定向到Python中的文件?

    from contextlib import redirect_stdoutwith open('help.txt', 'w') as f: with redirect_stdout(f): prin ...

  2. python移动文件中某个内容_如何在Python中移动文件

    如何在Python中移动文件 我查看了Python $ mv ...接口,但无法找到移动文件的方法. 我如何在Python中执行相当于$ mv ...的操作? >>> source_ ...

  3. python中读取文件过程中seek()函数的使用

    python中读取文件过程中seek()函数的使用 目录 概述: 语法: 参数: 返回值: 实例: 概述: seek() 方法用于移动文件读取指针到指定位置. 语法: seek() 方法语法如下: 文 ...

  4. python中csv文件操作_python中操作csv文件

    python中操作csv文件 读取csv improt csv f = csv.reader(open("文件路径","r")) for i in f: pri ...

  5. python操作目录_详解python中的文件与目录操作

    详解python中的文件与目录操作 一 获得当前路径 1.代码1 >>>import os >>>print('Current directory is ',os. ...

  6. python导入其他py文件-Python中py文件引用另一个py文件变量的方法

    最近自己初学Python,在编程是遇到一个问题就是,怎样在一个py文件中使用另一个py文件中变量,问题如下: demo1代码 import requests r = requests.get(&quo ...

  7. python如何读取txt文件-如何在python中读取文件夹中的txt文件列表

    注意:我在答案的最后写了这些函数,所以请随意跳转到那个 – 但是为了更好地理解,我仍然希望逐个部分地运行代码. 将用于解释的示例方案 假设您在此文件夹中有12个名为test的文件,其中10个是.txt ...

  8. python中对文件、文件夹(文件操作函数)的操作

    python中对文件.文件夹(文件操作函数)的操作需要涉及到os模块和shutil模块. 得到当前工作目录,即当前Python脚本工作的目录路径: os.getcwd() 返回指定目录下的所有文件和目 ...

  9. python中二进制文件_Python学习基础篇 -6: Python中的文件操作

    前言:本专栏以Python为主题,并尽可能保持每星期两到三更,直到将Python的基础知识浅析和讲解完毕,同时,有一定基础的同学可以移步 Python实战专栏 . 文件有有什么用 文件可以看作一个仓库 ...

最新文章

  1. 实战并发编程 - 01多线程读写同一共享变量的线程安全问题深入剖析
  2. 基于运维网V8环境安装ntop
  3. java学习(165):inetaddress和inetsocketaddress
  4. 11.深度学习练习:Keras tutorial - the Happy House(推荐)
  5. 数据结构基础(6) --顺序栈的设计与实现
  6. mysql datetime 比较大小_【知识点】分布式事务数据库 —-MySQL 数据库开发规范(第一节)...
  7. JavaScript正则式练习
  8. LTE技术派报告:LTE抛弃了CDMA?
  9. 表白公式计算机,【理工男表白公式大全】_理工男写“公式体”情书表白图
  10. 专科学历去学计算机,前景到底如何?
  11. 快速幂算法(全网最详细地带你从零开始一步一步优化)
  12. Centos7上搭建迅雷远程下载服务器
  13. java构造方法是什么_java中什么叫构造方法,作用是什么?
  14. 电子商城后台系统(一):使用eclipse构建web项目
  15. 逼死程序员的翟某被媒体起底,疑有 5 个对象离了 4 次获利上亿
  16. 精细化运营时代,金融魔镜如何助力各产品线实现业务增长
  17. word2003计算机考试题,职称计算机考试试题库—word2003.pdf
  18. 第十四届蓝桥杯三月真题刷题训练——第 19 天
  19. jpa 使用hql进行联表查询
  20. 计算机专业可以考事业单位a类吗,事业单位A类考什么?

热门文章

  1. 基于事件驱动的微服务教程
  2. 经典分类算法——SVM算法
  3. 2015个人年终总结
  4. 红粉NBA:那些在联盟中的跨国恋情
  5. Moe Wallpaper 桌面动态壁纸设置器V2.3
  6. python怎么输出列表中元素的索引_python怎么获取列表元素的索引
  7. inspeckage使用实战两例
  8. Java基础(28)数据输入输出流、内存操作流、打印流、随机访问流、序列化与反序列化流、Properties类(集合)
  9. await原理 js_JavaScript async/await原理及实例解析
  10. 传教士与野人问题的C++搜索实现