Python 文件上下文或 None
Python context for file or None
Python 将调用一个子进程,用户要么请求子进程 stdout 转到一个文件(或返回到 os.devnull),要么子进程输出是通过 "in real time".
我目前的最佳猜测似乎可行:
- 让
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)
在 tinkering/testing 中,这似乎是正确的值,我认为它与 subprocess.call 配合得很好。但是,毫不奇怪,我得到以下异常:
AttributeError: __exit__
所以None
不是上下文,它没有__exit__
;
目标
- 如果用户不想记录,则根本不打开文件。
- 使用上下文(由 stdlib 提供),(首选项;我无法想象手动执行文件 open/close 操作会更干净。)
- 不需要try/catch(避免进一步嵌套的偏好)
- 只调用一次
subprocesses.call
(非重复行)
那么,如何实现这种行为呢?或者你会建议做什么 instead/alternatively?
您可以创建 "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
时,条件表达式returns一个文件对象。当 logging
为 False 时,它 returns 一个 noop()
上下文管理器(因此它可以在 with-statement
中使用),它将 shell_out
设置为 None
但在退出时没有做任何特别的事情。
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()
可能有助于将标准输出定向到父级的标准输出,这可能与 sys.stdout
不同。
如果这个极端情况不影响你,那么就更简单了:
with open(file_path, 'wb') if logging else sys.stdout as shell_stdout:
subprocess.call(['ls'], stdout=shell_stdout)
将shell_stdout
设置为stdout
或file object
基于日志记录是真还是假,没有必要过于复杂,你只有一个条件或另一个if logging
要么是 True 要么是 False,不使用 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
:
with open(file_path, 'wb') if logging else sys.stdout as shell_stdout:
subprocess.call(['ls'], stdout=shell_stdout)
仅当日志记录为 True 时才会创建文件。
从 Python 3.3 开始,您可以使用 contextlib.ExitStack
:
定义无操作上下文管理器
from contextlib import ExitStack
with open(...) if ... else ExitStack():
...
Python 将调用一个子进程,用户要么请求子进程 stdout 转到一个文件(或返回到 os.devnull),要么子进程输出是通过 "in real time".
我目前的最佳猜测似乎可行:
- 让
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)
在 tinkering/testing 中,这似乎是正确的值,我认为它与 subprocess.call 配合得很好。但是,毫不奇怪,我得到以下异常:
AttributeError: __exit__
所以None
不是上下文,它没有__exit__
;
目标
- 如果用户不想记录,则根本不打开文件。
- 使用上下文(由 stdlib 提供),(首选项;我无法想象手动执行文件 open/close 操作会更干净。)
- 不需要try/catch(避免进一步嵌套的偏好)
- 只调用一次
subprocesses.call
(非重复行)
那么,如何实现这种行为呢?或者你会建议做什么 instead/alternatively?
您可以创建 "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
时,条件表达式returns一个文件对象。当 logging
为 False 时,它 returns 一个 noop()
上下文管理器(因此它可以在 with-statement
中使用),它将 shell_out
设置为 None
但在退出时没有做任何特别的事情。
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()
可能有助于将标准输出定向到父级的标准输出,这可能与 sys.stdout
不同。
如果这个极端情况不影响你,那么
with open(file_path, 'wb') if logging else sys.stdout as shell_stdout:
subprocess.call(['ls'], stdout=shell_stdout)
将shell_stdout
设置为stdout
或file object
基于日志记录是真还是假,没有必要过于复杂,你只有一个条件或另一个if logging
要么是 True 要么是 False,不使用 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
:
with open(file_path, 'wb') if logging else sys.stdout as shell_stdout:
subprocess.call(['ls'], stdout=shell_stdout)
仅当日志记录为 True 时才会创建文件。
从 Python 3.3 开始,您可以使用 contextlib.ExitStack
:
from contextlib import ExitStack
with open(...) if ... else ExitStack():
...