处理 None 和 with Statement 的 Pythonic 方法
Pythonic Method for handling None and with Statement
我想调用一个函数并传递一个 File
类对象或 None
。但是,使用类似 File
的对象,我想使用 with
语句正确处理其资源分配。但是,如果我的 with
表达式的计算结果为 None
,Python 将引发异常 (AttributeError
)。我想我可以手写完整的 try
/except
块,但是是否存在处理这种情况的简洁 Pythonic 方法?
def call_method(o1, o2, f_in):
if f_in:
pass # Do something optional if we have the f_in value
# ...
with (open(path, 'rb') if flag else None) as f_in:
call_method(opt1, opt2, f_in)
# Throws an AttributeError, since None does not have __exit__
这样做的方法是使用 try/except:
try:
with open(path) as f:
...
except OSError:
pass
上面的代码是如果你打算对文件做些什么/改变它以避免竞争条件。
事实上,您不能将 None
传递给 with
,因为 with
完成后会调用 __exit__
。相反,重新排列为:
def call_method(o1, o2, f_in):
# If nothing special is done with None (just a pass) then you don't
# even need to call this with None, otherwise, you can check f_in like:
if f_in is None:
pass
else:
pass
if flag:
with open(path, 'rb') as f_in:
call_method(opt1, opt2, f_in)
else:
# only really needed if call_method does something if None is passed
call_method(opt1, opt2, None)
另一种选择是使用 nullcontext()
代替另一个答案中所述的 None
如果您想要一个什么都不做的上下文管理器,那就是 contextlib.nullcontext()
,而不是 None
:
import contextlib
with (open(whatever) if flag else contextlib.nullcontext()) as f:
do_whatever()
f
在 not flag
的情况下将是 None
- 分配给 f
的东西是 __enter__
的 return值,不必是上下文管理器本身。
对于 Python < 3.7,我用 lambda
表达式完成了这个:
def call_method(o1, o2, get_file):
if get_file:
with (get_file() as f_in):
pass # Do something optional if we have the f_in value
# ...
get_file = (lambda: open(path, 'rb')) if flag else None
call_method(opt1, opt2, get_file)
我想调用一个函数并传递一个 File
类对象或 None
。但是,使用类似 File
的对象,我想使用 with
语句正确处理其资源分配。但是,如果我的 with
表达式的计算结果为 None
,Python 将引发异常 (AttributeError
)。我想我可以手写完整的 try
/except
块,但是是否存在处理这种情况的简洁 Pythonic 方法?
def call_method(o1, o2, f_in):
if f_in:
pass # Do something optional if we have the f_in value
# ...
with (open(path, 'rb') if flag else None) as f_in:
call_method(opt1, opt2, f_in)
# Throws an AttributeError, since None does not have __exit__
这样做的方法是使用 try/except:
try:
with open(path) as f:
...
except OSError:
pass
上面的代码是如果你打算对文件做些什么/改变它以避免竞争条件。
事实上,您不能将 None
传递给 with
,因为 with
完成后会调用 __exit__
。相反,重新排列为:
def call_method(o1, o2, f_in):
# If nothing special is done with None (just a pass) then you don't
# even need to call this with None, otherwise, you can check f_in like:
if f_in is None:
pass
else:
pass
if flag:
with open(path, 'rb') as f_in:
call_method(opt1, opt2, f_in)
else:
# only really needed if call_method does something if None is passed
call_method(opt1, opt2, None)
另一种选择是使用 nullcontext()
代替另一个答案中所述的 None
如果您想要一个什么都不做的上下文管理器,那就是 contextlib.nullcontext()
,而不是 None
:
import contextlib
with (open(whatever) if flag else contextlib.nullcontext()) as f:
do_whatever()
f
在 not flag
的情况下将是 None
- 分配给 f
的东西是 __enter__
的 return值,不必是上下文管理器本身。
对于 Python < 3.7,我用 lambda
表达式完成了这个:
def call_method(o1, o2, get_file):
if get_file:
with (get_file() as f_in):
pass # Do something optional if we have the f_in value
# ...
get_file = (lambda: open(path, 'rb')) if flag else None
call_method(opt1, opt2, get_file)