[英]Multiple with statements in Python 2.7 using a list comprehension
I am interested in doing a list comprehension inside a Python with
statement, so that I can open multiple context managers at the same time with minimal syntax. 我有兴趣做一个列表理解Python的内部 with
的语句,这样我就可以在同一时间以最小的语法打开多个方面的经理。 I am looking for answers that work with Python 2.7 . 我正在寻找适用于Python 2.7的答案。
Consider the following code example. 考虑下面的代码示例。 I want to use the with
statement on variables in an arbitrarily-long list at the same time , preferably in a syntactically-clean fashion. 我想同时对任意长列表中的变量使用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")
Does anybody know if there is a way to involve a list comprehension inside of a with
statement in Python 2.7 ? 是否有人知道在Python 2.7的with
语句内部是否包含涉及列表理解的方法?
Here are some things I've already looked at, with an explanation of why they do not suit my purposes: 这是我已经看过的一些内容,并解释了为什么它们不适合我的目的:
For Python 2.6- , I could use contextlib.nested
to accomplish this a bit like: 对于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)
However, this is deprecated in Python 2.7+ , so I am assuming it is bad practice to use. 但是, Python 2.7+中不推荐使用此方法,因此我认为使用它是不好的做法。
Instead, the new syntax was given on this SO answer , as well as this SO answer : 相反,新的语法得到了关于这个苏答案 ,以及这个苏答案 :
with A() as a, B() as b, C() as c:
doSomething(a,b,c)
However, I need to be able to deal with an arbitrary input list, as in the example I gave above. 但是,我需要能够处理一个任意输入列表,如上面的示例所示。 This is why I favour list comprehension. 这就是为什么我赞成列表理解。
For Python 3.3+ , this SO answer described how this could be accomplished by using ExitStack
. 对于Python 3.3+ , 此SO答案描述了如何使用ExitStack
来完成此任务。 However, I am working in Python 2.7. 但是,我正在使用Python 2.7。
There is also this solution , but I would prefer to not write my own class to accomplish this. 也有此解决方案 ,但是我不希望自己编写类来完成此任务。
Is there any hope of combining a list comprehension and a with
statement in Python 2.7? 是否有希望在Python 2.7中结合使用列表理解和with
语句?
Update 1-3: Updated example to better emphasize the functionality I am looking for 更新1-3:更新示例以更好地强调我正在寻找的功能
Update 4: Found another similar question . 更新4:发现了另一个类似的问题 。 This one has an answer which also suggests ExitStack
, a function that is not available in 2.7. 这个有一个答案,也建议使用ExitStack
,该功能在2.7中不可用。
The major tasks of with
statement is invoking the __exit__
attribute of its context manager. with
语句的主要任务是调用其上下文管理器的__exit__
属性。 Specially for dealing with files. 专门用于处理文件。 So In this case due to this point and the fact that open()
returns an file_object
you can dimple use a list comprehension in order to create the list of your file objects and just call the exit()/close()
manually. 因此,在这种情况下,由于这一点以及open()
返回file_object
的事实,您可以使用列表理解来酒窝以创建文件对象的列表,而只需手动调用exit()/close()
。 But be aware that in this case you have to handle the exceptions manually. 但是请注意,在这种情况下,您必须手动处理异常。
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()
Note that if you only want to run some parallel operations on your file objects, I recommend this approach, other wise the best way is using a with
statement inside a for loop, and opennning the files in each iteration (on names) like following: 请注意,如果只想对文件对象运行一些并行操作,则建议使用此方法,否则,最好的方法是在for循环内使用with
语句,并在每次迭代(按名称)中打开文件,如下所示:
for arg in args:
with open(arg) as f:
# Do something with f
For more safety you can use a custom open
function in order to handle the exceptions too: 为了更加安全,您也可以使用自定义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
Doing this yourself is really tricky, especially handling exceptions that occur while opening or closing the files. 自己执行此操作确实很棘手,尤其是处理打开或关闭文件时发生的异常。 I'd recommend just getting a library like contextlib2
that implements the contextlib.ExitStack
functionality. 我建议仅获取一个实现contextlib.ExitStack
功能的诸如contextlib2
类的库。 Then you can do 那你可以做
with contextlib2.ExitStack() as stack:
files = [stack.enter_context(open(arg)) for arg in args]
...
just like you were using contextlib.ExitStack
from Python 3, and everything is handled correctly for you. 就像您在使用Python 3中的contextlib.ExitStack
一样,一切都已为您正确处理。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.