我有兴趣在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以及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,但我宁愿不写自己的课来完成这项工作。
是否有希望在Python 2.7中结合使用列表推导和with
语句?
更新1-3:更新示例以更好地强调我正在寻找的功能
更新4:找到另一个similar question 。这个答案也提出了ExitStack
,这个函数在2.7中没有。
答案 0 :(得分:2)
with
语句的主要任务是调用其上下文管理器的__exit__
属性。特别用于处理文件。因此,在这种情况下,由于这一点以及open()
返回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
答案 1 :(得分:2)
自己这样做非常棘手,特别是处理打开或关闭文件时发生的异常。我建议您只使用contextlib2
这样的库来实现contextlib.ExitStack
功能。然后就可以了
with contextlib2.ExitStack() as stack:
files = [stack.enter_context(open(arg)) for arg in args]
...
就像你在Python 3中使用contextlib.ExitStack
一样,一切都正确处理。