文件或无的 Python 上下文

标签 python file-handling with-statement

Python 将调用一个子进程,用户要么请求子进程 stdout 转到一个文件(或返回到 os.devnull),要么子进程输出将“实时”传递。

我目前最好的猜测是如何做到这一点似乎可行:

  • file_path 成为 open() 的有效输入
  • logging 为 bool 指示符,true 表示使用 file_path 进行日志记录,false 表示直通到 stdout。

with open(file_path, 'wb') if logging else None as shell_stdout:
    subprocess.call(['ls'], stdout=shell_stdout)

在修补/测试中,这似乎是正确的值,我假设它与 subprocess.call 一起工作。但是,毫不奇怪,我得到以下异常:

AttributeError: __exit__

所以None不是上下文,它没有__exit__


目标

  • 如果用户不想记录,则根本不打开文件。
  • 使用上下文(由 stdlib 提供),(首选项;我无法想象手动执行文件打开/关闭操作会更干净。)
  • 不需要 try/catch(避免进一步嵌套的偏好)
  • 只调用一次subprocesses.call(非重复行)

那么,如何实现这种行为呢?或者你会建议做什么来代替/替代?

最佳答案

您可以创建一个“无操作”context manager :

import subprocess
import contextlib
@contextlib.contextmanager
def noop():
    yield None

logging = False
file_path = '/tmp/out'

with open(file_path, 'wb') if logging else noop() as shell_stdout:
    subprocess.call(['ls'], stdout=shell_stdout)

当 logging 为 True 时,条件表达式返回一个文件对象。当 logging 为 False 时,它​​返回一个 noop() 上下文管理器(因此它可以在 with-statement 中使用),它设置 shell_outNone 但在退出时不执行任何特殊操作。


Per the docs , 当 stdout=None,

... no redirection will occur; the child’s file handles will be inherited from the parent.

通常父级的标准输出等于 sys.stdout。但是,可以将 sys.stdout 重定向到其他地方,无论是显式(例如 sys.stdout = open('/tmp/stdout', 'wb'))还是间接地,例如通过使用重定向 sys.stdout 的模块。例如,标准库中的 fileinput 模块重定向 sys.stdout。在这种情况下,noop() 可能有助于将 stdout 定向到父级的 stdout,这可能与 sys.stdout 不同。

如果这个角落案例不影响你,那么Padraic Cunningham's solution更简单:

with open(file_path, 'wb') if logging else sys.stdout as shell_stdout:
    subprocess.call(['ls'], stdout=shell_stdout)

关于文件或无的 Python 上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28680442/

相关文章:

python - 限制对仅拥有的内容 django 的访问

python - 将 pandas Series 作为列添加到 DataFrame 时出现 Wild NaN

Python:Next() 不断给出错误 StopIteration

python - 计算 python 文件中每个类的代码行数?

python - With 子句用于 Python 中的多处理

c - 使用 GIO 处理文件

python - 如何阻止它返回 "\n"以及列表中的数据?

c++ - 文件处理 C++ 时出错

python - 在类里面发表声明

python - 跳过 -with- block 的执行