在Python 2.7中使用列表理解的多个with语句 问题:
我感兴趣的是使用语句在Python在Python 2.7中使用列表理解的多个with语句 问题:,python,python-2.7,list-comprehension,with-statement,Python,Python 2.7,List Comprehension,With Statement,我感兴趣的是使用语句在Python中进行列表理解,这样我就可以用最少的语法同时打开多个上下文管理器。我正在寻找与Python 2.7兼容的答案 考虑下面的代码示例。我想同时对任意长的列表中的变量使用with语句,最好是以语法清晰的方式 def do_something(*args): contexts = {} with [open(arg) as contexts[str(i)] for i, arg in enumerate(args)]: do_anothe
中进行列表理解,这样我就可以用最少的语法同时打开多个上下文管理器。我正在寻找与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")
有人知道在Python2.7中的with
语句中是否有一种包含列表理解的方法吗
对类似问题的答复:
以下是我已经看过的一些东西,并解释了为什么它们不适合我的目的:
对于Python2.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+中是不推荐的,所以我认为使用它是不好的做法
相反,在上给出了新语法,以及:
但是,我需要能够处理任意的输入列表,如我上面给出的示例所示。这就是为什么我喜欢列表理解
对于Python 3.3+,描述了如何使用ExitStack
实现这一点。但是,我使用的是Python 2.7
也有,但我宁愿不写我自己的类来完成这一点
在Python2.7中,是否有希望将列表理解和语句与语句结合起来
更新1-3:更新示例以更好地强调我正在寻找的功能
更新4:找到另一个。这个问题的答案也表明了ExitStack
,这是一个在2.7中不可用的函数。带有语句的的主要任务是调用其上下文管理器的\uuuuuuu退出
属性。专门处理文件。因此,在这种情况下,由于这一点以及open()
返回file\u对象的事实,您可以使用列表理解来创建文件对象的列表,只需手动调用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
为了更安全,您也可以使用自定义的打开
功能来处理异常:
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
自己做这件事真的很棘手,尤其是处理打开或关闭文件时发生的异常。我建议只获得一个实现contextlib.ExitStack
功能的库。那你就可以了
with contextlib2.ExitStack() as stack:
files = [stack.enter_context(open(arg)) for arg in args]
...
就像您使用Python 3中的contextlib.ExitStack
一样,一切都得到了正确的处理。这就像是一个“我有ship1=1;ship2=2
代码,现在我想要无限数量的ship,我如何在代码中用新的数字创建ship变量???这可能吗?”毫无意义的问题。循环使用with语句<代码>对于列表中的项:将open(item)作为f:f.read()
…我需要能够同时打开所有上下文管理器,例如,将open(item1)作为f1:将open(item2)作为f2:#对两者都做些什么。我也有任意数量的项目。更新了我的示例,以显示上下文管理器需要如何同时打开,而不仅仅是按顺序打开。这没有与或ExitStack
的异常安全好处,尤其是在打开其中一个文件失败时。@user2357112确实,还有exit()期间的异常
。感谢您的回答@Kasramvd。不幸的是,正如@user2357112所指出的,您的示例没有使用
的
所带来的安全好处,这正是我想要的。是的,我希望做一些与物体平行的事情。@Miles是的,这是一个很好的观点。在这种情况下,我认为你必须像退出那样手动操作。可能使用装饰器或其他功能,检查编辑。如果在打开和关闭之间发生异常,您不会关闭文件;最后你需要试一下。另外,与手动处理相比,ExitStack
的一个主要优点是,它允许您干净地传播安装或拆卸过程中发生的异常。对于手动处理,传播它们而不是使它们沉默是非常尴尬的。谢谢@user2357112-这绝对是解决我问题的好办法。但是,我想在Python2.7本身中使用一些东西,而不必导入外部库。但是,如果没有这样的答案,我将接受你的答案!
with contextlib2.ExitStack() as stack:
files = [stack.enter_context(open(arg)) for arg in args]
...