with 关键字在打开文件时有效,但在调用函数时无效
Posted
技术标签:
【中文标题】with 关键字在打开文件时有效,但在调用函数时无效【英文标题】:with keyword works when openning file but not when calling a function 【发布时间】:2015-11-25 21:49:52 【问题描述】:我正在试验多处理模块并从this 页面复制示例代码。这是一个例子:
#!/usr/bin/python
from multiprocessing import Pool
from time import sleep
def f(x):
return x*x
if __name__ == '__main__':
# start 4 worker processes
with Pool(processes=4) as pool:
# print "[0, 1, 4,..., 81]"
print(pool.map(f, range(10)))
# print same numbers in arbitrary order
for i in pool.imap_unordered(f, range(10)):
print(i)
# evaluate "f(10)" asynchronously
res = pool.apply_async(f, [10])
print(res.get(timeout=1)) # prints "100"
# make worker sleep for 10 secs
res = pool.apply_async(sleep, [10])
print(res.get(timeout=1)) # raises multiprocessing.TimeoutError
# exiting the 'with'-block has stopped the pool
运行此代码后,我得到:
Traceback (most recent call last):
File "example01.py", line 11, in <module>
with Pool(processes=4) as pool:
AttributeError: __exit__
不知何故,我发现这是由于 with
关键字。然而,这段代码也在使用with
并且它正在运行:
#!/usr/bin/python
with open("input.csv", "wb") as filePath:
pass
filePath.close()
当我想运行提到的示例时,我必须按照以下方式对其进行修改:
#!/usr/bin/python
from multiprocessing import Pool
from time import sleep
import traceback
def f(x):
return x*x
if __name__ == '__main__':
# start 4 worker processes
# with Pool(processes=4) as pool:
try:
pool = Pool(processes = 4)
# print "[0, 1, 4,..., 81]"
print(pool.map(f, range(10)))
# print same numbers in arbitrary order
for i in pool.imap_unordered(f, range(10)):
print(i)
# evaluate "f(10)" asynchronously
res = pool.apply_async(f, [10])
print(res.get(timeout=1)) # prints "100"
# make worker sleep for 10 secs
res = pool.apply_async(sleep, [10])
print(res.get(timeout=1)) # raises multiprocessing.TimeoutError
# exiting the 'with'-block has stopped the pool
# http://***.com/questions/4990718/python-about-catching-any-exception
# http://***.com/questions/1483429/how-to-print-an-error-in-python
# http://***.com/questions/1369526/what-is-the-python-keyword-with-used-for
except Exception as e:
print "Exception happened:"
print type(e)
print str(e)
print traceback.print_exc()
然后输出如下所示:
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
0
1
4
9
16
25
36
49
64
81
100
Exception happened:
<class 'multiprocessing.TimeoutError'>
Traceback (most recent call last):
File "example01_mod.py", line 29, in <module>
print(res.get(timeout=1)) # raises multiprocessing.TimeoutError
File "/usr/lib/python2.7/multiprocessing/pool.py", line 563, in get
raise TimeoutError
TimeoutError
None
为什么我在使用 with
关键字时会出错,这些代码(带有和 try-catch)是等效的吗?我正在使用 python 2.7.10。
【问题讨论】:
您不能只将with
用于任何对象。对象必须是context manager。
【参考方案1】:
This PEP 描述了使用“with”关键字所需的上下文管理器接口。 Python 2.7 的 Pool 类版本不支持此接口,因此您不能按照您描述的方式使用“with”关键字。
您可以像the example here 那样直接重写代码以不使用并加入/终止池,或者您可以升级到支持池的“with”的 Python 3。
【讨论】:
您能否解释一下“上下文管理器”的含义以及“重写代码以不使用并直接加入池”的含义?并且是否可以简要解释为什么它在 python3 中工作,我的意思是它是 Pool 的问题,或者它是 python3 的特性还是什么?谢谢 为什么这在 python3 中工作可能由@Abhijit 解释“池已从 Python 3.4.3 转换为上下文管理器对象,如果您的版本早于该版本,则不能将其与上下文管理器一起使用。”如果我错了,请纠正我,PS:我不是英语母语。【参考方案2】:您错误地假设multiprocessor Pool class of Python 2.7 返回context manager。相反,它返回worker processes 的列表。 Pool 已从 Python 3.4.3 转换为上下文管理器对象,如果您的版本早于该版本,则不能将其与上下文管理器一起使用。
要与 with 语句一起使用,表达式应该返回一个带有 enter 和 exit 方法的对象,以便您得到熟悉的错误。
AttributeError: __exit_
【讨论】:
您能简单解释一下什么是上下文管理器吗?从您的问题来看,with
关键字似乎使用了某种数据类型。谢谢
@WakanTanka:我已经更新了链接到文档相关部分的答案,解释了什么是上下文管理器。以上是关于with 关键字在打开文件时有效,但在调用函数时无效的主要内容,如果未能解决你的问题,请参考以下文章
电子邮件附件的存储名称 - 第一次运行时出错,但在第二次运行时有效
此 SQL 代码在 SMMS 中执行时有效,但在 .Net 中通过 ExecuteNonQuery() 调用时无效,为啥?
NSFileManager 在 Xcode 中作为发行版构建时有效,但在作为独立 OS X Cocoa 应用程序运行时无效
HTML5 视频未在 chrome 中加载,但在打开开发人员控制台时有效