Python将调用子进程,用户要么子进程stdout要转到文件(或者回溯到os.devnull),要么子进程输出通过"实际时间"
我目前最好的猜测是如何做到这一点似乎有效:
file_path
成为open()
logging
成为布尔指示符,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__
;
subprocesses.call
(非重复行)那么,这种行为怎么能实现呢?或者你会建议做什么/替代?
答案 0 :(得分:7)
你可以创建一个" no-op" 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)
当记录为True
时,条件表达式返回一个文件对象。当logging
为False时,它会返回noop()
上下文管理器(因此可以在with-statement
中使用),这会将shell_out
设置为None
但不会# 39;退出时做任何特别的事。
Per the docs,stdout=None
时,
......不会发生重定向;子项的文件句柄将从父项继承。
通常父母的标准输出将等于sys.stdout
。但是,可以明确地(例如sys.stdout
)或间接地将sys.stdout = open('/tmp/stdout', 'wb')
重定向到其他位置,例如通过使用重定向sys.stdout
的模块。例如,标准库中的fileinput
模块会重定向sys.stdout
。在这种情况下,noop()
可能有助于将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)
答案 1 :(得分:3)
根据记录为True或False,将shell_stdout
设置为stdout
或file object
,无需过度复杂化,只有一个条件或另一个{{1无论是True还是False,打开不使用if logging
的文件都没有错,有时使用with
不合适。
with
要在您的问题中执行您想要的操作,您可以执行以下操作,您不需要任何条形import sys
if logging:
shell_stdout = open(file_path, 'wb') # to file or devnull if logging
else:
shell_stdout = sys.stdout
subprocess.call(['ls'], stdout=shell_stdout) # real time if not logging
shell_stdout.close()
:
sys.stdout
只有在记录为True时才会创建文件。
答案 2 :(得分:0)
从Python 3.3开始,tou可以使用contextlib.ExitStack
定义一个无操作的上下文管理器:
from contextlib import ExitStack
with open(...) if ... else ExitStack():
...