【问题标题】:python - prevent IOError: [Errno 5] Input/output error when running without stdoutpython - 防止 IOError: [Errno 5] 在没有标准输出的情况下运行时输入/输出错误
【发布时间】:2016-07-07 05:34:12
【问题描述】:

我有一个通过 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()

from __future__ import print_function
import __builtin__

def print(*args, **kwargs):
        pass
    __builtin__.print = print

但这些都不起作用。我认为它只影响模块本身,而不影响我稍后导入/运行的模块。

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

谢谢,

【问题讨论】:

    标签: python python-2.7 stdout


    【解决方案1】:

    修改内置函数或更改 sys.stdout应该 工作(子进程除外——但你排除了这些)只要你做得足够早。不过,如果没有,还有一个更简单的低级技巧:

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

      python foo.py >/dev/null 2>&1
      

      (假设 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)
      

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

    话虽如此,一个好的 cron 确实应该在某个地方连接 stdout 和 stderr,并且应该通过电子邮件将输出/错误输出发送给您。不过,并非所有 cron 版本都这么好。

    【讨论】:

    • 第一个简单的解决方案为我做到了。好答案,谢谢! :)
    • 第一个更好,因为这意味着您的程序在正常运行时仍然可以产生正常的输出。
    • 另一种解决方案是使用 nohup 运行脚本:nohup python script.py。这个命令对我来说适用于 kubernetes cron 作业。
    • @Olshansk:是的,nohup(或至少它的某些版本)安排了有效的标准输入、标准输出和标准错误描述符。 FreeBSD 版本的文档只提到了 stdout 和 stderr; Linux 文档提到了所有这三个。
    猜你喜欢
    • 1970-01-01
    • 2023-03-15
    • 2021-09-11
    • 2019-09-21
    • 2018-10-29
    • 2015-03-26
    • 1970-01-01
    • 2012-05-11
    • 1970-01-01
    相关资源
    最近更新 更多