[英]Is it possible to have an optional with/as statement in python?
Instead of this:取而代之的是:
FILE = open(f)
do_something(FILE)
FILE.close()
it's better to use this:最好使用这个:
with open(f) as FILE:
do_something(FILE)
What if I have something like this?如果我有这样的事情怎么办?
if f is not None:
FILE = open(f)
else:
FILE = None
do_something(FILE)
if FILE is not None:
FILE.close()
Where do_something also has an "if FILE is None" clause, and still does something useful in that case - I don't want to just skip do_something if FILE is None.哪里还do_something有一个“如果文件是无”的条款,而且还做一些有用的事情在这种情况下-我不希望只是跳过do_something如果FILE是无。
Is there a sensible way of converting this to with/as form?有没有一种明智的方式将其转换为 with/as 形式? Or am I just trying to solve the optional file problem in a wrong way?
还是我只是想以错误的方式解决可选文件问题?
If you were to just write it like this:如果你只是这样写:
if f is not None:
with open(f) as FILE:
do_something(FILE)
else:
do_something(f)
( file
is a builtin btw ) (
file
是内置的顺便说一句)
Update更新
Here is a funky way to do an on-the-fly context with an optional None that won't crash:这是一种使用不会崩溃的可选 None 进行动态上下文的时髦方法:
from contextlib import contextmanager
none_context = contextmanager(lambda: iter([None]))()
# <contextlib.GeneratorContextManager at 0x1021a0110>
with (open(f) if f is not None else none_context) as FILE:
do_something(FILE)
It creates a context that returns a None value.它创建了一个返回 None 值的上下文。 The
with
will either produce FILE as a file object, or a None type. with
要么产生 FILE 作为文件对象,要么产生 None 类型。 But the None type will have a proper __exit__
但是 None 类型会有一个适当的
__exit__
Update更新
If you are using Python 3.7 or higher, then you can declare the null context manager for stand-in purposes in a much simpler way:如果您使用的是 Python 3.7或更高版本,那么您可以以更简单的方式声明空上下文管理器用于替代目的:
import contextlib
none_context = contextlib.nullcontext()
You can read more about these here:您可以在此处阅读有关这些的更多信息:
https://docs.python.org/3.7/library/contextlib.html#contextlib.nullcontext https://docs.python.org/3.7/library/contextlib.html#contextlib.nullcontext
Since Python 3.7, you can also do从 Python 3.7 开始,你也可以这样做
from contextlib import nullcontext
with (open(file) if file else nullcontext()) as FILE:
# Do something with `FILE`
pass
See the official documentation for more details.有关更多详细信息,请参阅官方文档。
This seems to solve all of your concerns.这似乎解决了您的所有疑虑。
if file_name is not None:
with open(file_name) as fh:
do_something(fh)
else:
do_something(None)
something like:就像是:
if file: #it checks for None,false values no need of "if file is None"
with open(file) as FILE:
do_something(FILE)
else:
FILE=None
In Python 3.3 and above, you can use contextlib.ExitStack to handle this scenario nicely在 Python 3.3 及更高版本中,您可以使用contextlib.ExitStack很好地处理这种情况
with contextlib.ExitStack() as stack:
FILE = stack.enter_context(open(f)) if f else None
do_something(FILE)
Python 3.7 supports contextlib.nullcontext , which can be used to avoid creating your own dummy context manager. Python 3.7 支持contextlib.nullcontext ,可用于避免创建自己的虚拟上下文管理器。
This examples shows how you can conditionally open a file or use the stdout
:此示例显示了如何有条件地打开文件或使用
stdout
:
import contextlib
import sys
def write_to_file_or_stdout(filepath=None, data):
with (
open(filepath, 'w') if filepath is not None else
contextlib.nullcontext(sys.stdout)
) as file_handle:
file_handle.write(data)
contextlib.nullcontext()
can be called without any arguments if the value can be None.如果值可以是 None,则可以在没有任何参数的情况下调用
contextlib.nullcontext()
。
While all of the other answers are excellent, and preferable, note that the with
expression may be any expression, so you can do:虽然所有其他答案都很好,而且更可取,但请注意
with
表达式可以是任何表达式,因此您可以执行以下操作:
with (open(file) if file is not None else None) as FILE:
pass
Note that if the else
clause were evaluated, to yield None
this would result in an exception, because NoneType
does not support the appropriate operations to be used as a context manager.请注意,如果对
else
子句求值,则生成None
这将导致异常,因为NoneType
不支持用作上下文管理器的适当操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.