Python 2.7 中的多个 with 语句使用列表理解
Multiple with statements in Python 2.7 using a list comprehension
问题:
我有兴趣在 inside 一个 Python with
语句中做一个列表理解,这样我就可以同时打开多个上下文管理器最小的语法。我正在寻找适用于 Python 2.7.
的答案
考虑以下代码示例。我想同时对任意长列表 中的变量使用 with
语句 ,最好以语法清晰的方式使用。
def do_something(*args):
contexts = {}
with [open(arg) as contexts[str(i)] for i, arg in enumerate(args)]:
do_another_thing(contexts)
do_something("file1.txt", "file2.txt")
有人知道是否有办法在 Python 2.7 中的 with
语句中涉及列表理解吗?
类似问题的回答:
以下是我已经看过的一些内容,并解释了为什么它们不适合我的目的:
对于 Python 2.6-,我可以使用 contextlib.nested
来完成这个有点像:
def do_something(*args):
contexts = {}
with nested(*[open(arg) for arg in args]) as [contexts[str(i)] for i in range(len(args))]:
do_another_thing(contexts)
然而,这在 Python 2.7+ 中已被弃用,所以我认为使用它是不好的做法。
相反,新语法是在 this SO answer, as well as this SO answer 上给出的:
with A() as a, B() as b, C() as c:
doSomething(a,b,c)
但是,我需要能够处理任意输入列表,就像我上面给出的示例一样。这就是为什么我赞成列表理解。
对于 Python 3.3+,this SO answer 描述了如何使用 ExitStack
来完成。但是,我在 Python 2.7.
中工作
还有this solution,但我不想自己写class来完成这个。
是否有希望在 Python 2.7 中结合列表理解和 with
语句?
更新 1-3:更新示例以更好地强调我正在寻找的功能
更新 4:发现另一个 similar question。这个有一个答案也建议 ExitStack
,一个在 2.7 中不可用的函数。
with
语句的主要任务是调用其上下文管理器的 __exit__
属性。专门用于处理文件。因此,在这种情况下,由于这一点以及 open()
returns 和 file_object
的事实,您可以使用列表理解来创建文件对象列表并调用 exit()/close()
手动。但请注意,在这种情况下,您必须手动处理异常。
def print_files(*args):
f_objs = [open(arg) for arg in args]
# do what you want with f_objs
# ...
# at the end
for obj in f_objs:
f.close()
请注意,如果您只想 运行 对文件对象进行一些并行操作,我推荐这种方法,否则最好的方法是在 for 循环中使用 with
语句,并且在每次迭代中打开文件(按名称),如下所示:
for arg in args:
with open(arg) as f:
# Do something with f
为了更安全,您也可以使用自定义 open
函数来处理异常:
def my_open(*args, **kwargs):
try:
file_obj = open(*args, **kwargs)
except Exception as exp:
# do something with exp and return a proper object
else:
return file_obj
def print_files(*args):
f_objs = [my_open(arg) for arg in args]
# do what you want with f_objs
# ...
# at the end
for obj in f_objs:
try:
f.close()
except Exception as exp:
# handle the exception
自己做这件事真的很棘手,尤其是处理打开或关闭文件时发生的异常。我建议只获得一个像 contextlib2
这样实现 contextlib.ExitStack
功能的库。那么你可以做
with contextlib2.ExitStack() as stack:
files = [stack.enter_context(open(arg)) for arg in args]
...
就像您使用 Python 3 中的 contextlib.ExitStack
一样,一切都会为您正确处理。
问题:
我有兴趣在 inside 一个 Python with
语句中做一个列表理解,这样我就可以同时打开多个上下文管理器最小的语法。我正在寻找适用于 Python 2.7.
考虑以下代码示例。我想同时对任意长列表 中的变量使用 with
语句 ,最好以语法清晰的方式使用。
def do_something(*args):
contexts = {}
with [open(arg) as contexts[str(i)] for i, arg in enumerate(args)]:
do_another_thing(contexts)
do_something("file1.txt", "file2.txt")
有人知道是否有办法在 Python 2.7 中的 with
语句中涉及列表理解吗?
类似问题的回答:
以下是我已经看过的一些内容,并解释了为什么它们不适合我的目的:
对于 Python 2.6-,我可以使用 contextlib.nested
来完成这个有点像:
def do_something(*args):
contexts = {}
with nested(*[open(arg) for arg in args]) as [contexts[str(i)] for i in range(len(args))]:
do_another_thing(contexts)
然而,这在 Python 2.7+ 中已被弃用,所以我认为使用它是不好的做法。
相反,新语法是在 this SO answer, as well as this SO answer 上给出的:
with A() as a, B() as b, C() as c:
doSomething(a,b,c)
但是,我需要能够处理任意输入列表,就像我上面给出的示例一样。这就是为什么我赞成列表理解。
对于 Python 3.3+,this SO answer 描述了如何使用 ExitStack
来完成。但是,我在 Python 2.7.
还有this solution,但我不想自己写class来完成这个。
是否有希望在 Python 2.7 中结合列表理解和 with
语句?
更新 1-3:更新示例以更好地强调我正在寻找的功能
更新 4:发现另一个 similar question。这个有一个答案也建议 ExitStack
,一个在 2.7 中不可用的函数。
with
语句的主要任务是调用其上下文管理器的 __exit__
属性。专门用于处理文件。因此,在这种情况下,由于这一点以及 open()
returns 和 file_object
的事实,您可以使用列表理解来创建文件对象列表并调用 exit()/close()
手动。但请注意,在这种情况下,您必须手动处理异常。
def print_files(*args):
f_objs = [open(arg) for arg in args]
# do what you want with f_objs
# ...
# at the end
for obj in f_objs:
f.close()
请注意,如果您只想 运行 对文件对象进行一些并行操作,我推荐这种方法,否则最好的方法是在 for 循环中使用 with
语句,并且在每次迭代中打开文件(按名称),如下所示:
for arg in args:
with open(arg) as f:
# Do something with f
为了更安全,您也可以使用自定义 open
函数来处理异常:
def my_open(*args, **kwargs):
try:
file_obj = open(*args, **kwargs)
except Exception as exp:
# do something with exp and return a proper object
else:
return file_obj
def print_files(*args):
f_objs = [my_open(arg) for arg in args]
# do what you want with f_objs
# ...
# at the end
for obj in f_objs:
try:
f.close()
except Exception as exp:
# handle the exception
自己做这件事真的很棘手,尤其是处理打开或关闭文件时发生的异常。我建议只获得一个像 contextlib2
这样实现 contextlib.ExitStack
功能的库。那么你可以做
with contextlib2.ExitStack() as stack:
files = [stack.enter_context(open(arg)) for arg in args]
...
就像您使用 Python 3 中的 contextlib.ExitStack
一样,一切都会为您正确处理。