23

而不是这个:

FILE = open(f)
do_something(FILE)
FILE.close()

最好使用这个:

with open(f) as FILE:
    do_something(FILE)

如果我有这样的事情怎么办?

if f is not None:
   FILE = open(f)
else:
   FILE = None
do_something(FILE)
if FILE is not None:
    FILE.close()

do_something 也有一个“if FILE is None”子句,并且在这种情况下仍然会做一些有用的事情——如果 FILE 是 None,我不想跳过 do_something。

有没有一种明智的方法可以将其转换为 with/as 形式?还是我只是试图以错误的方式解决可选文件问题?

4

7 回答 7

25

如果你只是这样写:

if f is not None:
    with open(f) as FILE:
        do_something(FILE)
else:
    do_something(f)

file是内置的顺便说一句)

更新

这是一种使用不会崩溃的可选 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)

它创建一个返回 None 值的上下文。将with生成 FILE 作为文件对象或 None 类型。但是 None 类型将有一个适当的__exit__

更新

如果您使用的是 Python 3.7或更高版本,则可以以更简单的方式声明 null 上下文管理器用于替代目的:

import contextlib
none_context = contextlib.nullcontext()

您可以在此处阅读有关这些内容的更多信息:

https://docs.python.org/3.7/library/contextlib.html#contextlib.nullcontext

于 2012-08-28T22:11:47.560 回答
15

从 Python 3.7 开始,你也可以这样做

from contextlib import nullcontext

with (open(file) if file else nullcontext()) as FILE:
    # Do something with `FILE`
    pass

有关详细信息,请参阅官方文档。

于 2019-07-10T12:57:56.810 回答
4

这似乎解决了你所有的顾虑。

if file_name is not None:
    with open(file_name) as fh:
        do_something(fh)
else:
        do_something(None)
于 2012-08-28T22:12:50.287 回答
2

就像是:

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
于 2012-08-28T22:13:03.550 回答
1

在 Python 3.3 及更高版本中,您可以使用contextlib.ExitStack很好地处理这种情况

with contextlib.ExitStack() as stack:
    FILE = stack.enter_context(open(f)) if f else None
    do_something(FILE)
于 2021-10-06T12:28:16.207 回答
1

Python 3.7 支持contextlib.nullcontext,可用于避免创建自己的虚拟上下文管理器。

此示例显示如何有条件地打开文件或使用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()如果值可以为 None,则可以不带任何参数调用。

于 2021-10-14T00:40:12.033 回答
-3

虽然所有其他答案都很好,而且更可取,但请注意with表达式可以是任何表达式,因此您可以这样做:

with (open(file) if file is not None else None) as FILE:
    pass

请注意,如果对else子句进行了评估,那么产生None这将导致异常,因为NoneType不支持将适当的操作用作上下文管理器。

于 2012-08-28T22:17:10.503 回答