python - 防止IOError:[Errno 5]在没有stdout的情况下运行时输入/输出错误

Ron*_*ess 7 python stdout python-2.7

我有一个脚本通过cronjob在服务器上自动运行,它导入并运行其他几个脚本.

其中一些使用打印,这自然会创建,IOError: [Errno 5] Input/output error因为脚本运行时没有连接任何SSH /终端,因此没有正确的标准设置.

关于这个主题有很多问题,但我找不到任何实际解决它的人,假设我无法删除打印或更改执行的脚本.

我尝试了几件事,包括:

class StdOut(object):
    def __init__(self):
        pass
    def write(self, string):
        pass
sys.stdout = StdOut()
sys.stderr = StdOut()
Run Code Online (Sandbox Code Playgroud)

from __future__ import print_function
import __builtin__

def print(*args, **kwargs):
        pass
    __builtin__.print = print
Run Code Online (Sandbox Code Playgroud)

但它都不起作用.我认为它只会影响模块本身,而不会影响我以后导入/运行的模块.

那么如何创建一个会影响流程中所有模块的存根标准输出?就像我说的,我不想更改从主模块执行的脚本,但我可以更改导入模块中的所有内容.只是为了清除 - 一切都是进口的,没有新的流程产生等.

谢谢,

tor*_*rek 7

修改内置或更改sys.stdout 应该工作(除了子进程 - 但你已经排除了这些),只要你尽早完成.如果没有,那么更低级别的技巧会更容易:

  • 使用丢弃输出的I/O重定向运行python脚本:

    python foo.py >/dev/null 2>&1
    
    Run Code Online (Sandbox Code Playgroud)

    (假设Unix-y脚本,如问题中"cron"所暗示的那样)

  • 或者,重定向文件描述符1和2(与上面相同的想法,但在Python启动时完成,而不是作为cron调用命令的一部分):

    import os
    fd = os.open(os.devnull, os.O_RDWR)
    # NB: even if stdin is closed, fd >= 0
    os.dup2(fd, 1)
    os.dup2(fd, 2)
    if fd > 2:
        os.close(fd)
    
    Run Code Online (Sandbox Code Playgroud)

    (如果所有描述符都已关闭,则此特定位代码具有使/ dev/null充当stdin的副作用).[ 编辑:我开始,with open(...)然后切换到os.open并没有测试最终版本.现在修复.]

总而言之,一个好的cron确实应该将stdout和stderr连接到某处,并且应该将输出/错误输出通过电子邮件发送给您.不是所有的cron版本都很好.

  • 第一个更好,因为这意味着你的程序在正常运行时仍然可以产生正常输出. (2认同)