我逐渐熟悉Python的private void ItemDecreased(object sender, EventArgs e)
{
string textBoxName = HoweverYouGetTheDynamicTextBoxName();
// Assumptions:
// 1. ItemDecreased is a method on a Form or a UserControl.
// 2. There is only one TextBox with the given name in the Form or UserControl.
// 3. The TextBox is added to the Form or UserControl's Controls property.
TextBox tb = Controls.Find(textBoxName, true).OfType<TextBox>().SingleOrDefault();
if (tb is null)
{
// Couldn't find the text box for some reason.
}
// tb references the dynamically created text box.
}
模块。以下代码按预期工作:
multiprocessing
但是,现在,如果我在上面的代码周围包装一个函数,则不会执行#outputs 0 1 2 3
from multiprocessing import Pool
def run_one(x):
print x
return
pool = Pool(processes=12)
for i in range(4):
pool.apply_async(run_one, (i,))
pool.close()
pool.join()
语句(或至少将输出重定向):
print
如果将#outputs nothing
def run():
def run_one(x):
print x
return
pool = Pool(processes=12)
for i in range(4):
pool.apply_async(run_one, (i,))
pool.close()
pool.join()
的定义移到run_one
之外,那么当我调用run
时,输出将再次是预期的:
run()
我在这里想念什么?为什么第二个片段不打印任何内容?如果我只是调用#outputs 0 1 2 3
def run_one(x):
print x
return
def run():
pool = Pool(processes=12)
for i in range(4):
pool.apply_async(run_one, (i,))
pool.close()
pool.join()
函数而不是使用run_one(i)
,则这三个代码都将输出相同。
答案 0 :(得分:2)
Pool需要对发送给其工作进程的所有内容进行腌制(序列化)。酸洗实际上仅保存函数的名称,而酸洗则需要按名称重新导入该函数。 为此,该功能需要在顶层定义,嵌套功能将不能被子项导入,并且已经尝试对其进行腌制会引发异常:
from multiprocessing.connection import _ForkingPickler
def run():
def foo(x):
pass
_ForkingPickler.dumps(foo) # multiprocessing custom pickler;
# same effect with pickle.dumps(foo)
run()
# Out:
Traceback (most recent call last):
...
AttributeError: Can't pickle local object 'run.<locals>.foo'
之所以看不到异常,是因为Pool
已经在父级的酸洗任务期间开始捕获异常,并且仅当您在{{1 }}对象,当您调用.get()
时立即得到。
这就是为什么(对于Python 2)最好始终这样使用它,即使您的目标函数不返回任何内容(仍然返回隐式AsyncResult
):
pool.apply_async()
Python 3具有用于异步Pool方法的None
参数,您可以使用该参数来处理异常。