【发布时间】:2018-03-01 14:50:39
【问题描述】:
好的,这个让我把头发扯掉了:
我有一个多进程程序,每个工作人员都在执行给定的任务。
当 KeyboardInterrupt 来临时,我希望每个工作人员将其内部状态保存到文件中,以便下次可以从中断的地方继续。
但是...
看起来包含状态信息的字典在这发生之前就消失了!
怎么样? exit() 函数正在访问一个更全局范围的字典版本......事实证明,各种 run()(以及从属于 run())函数一直在创建自己的变量版本。
这没什么好奇怪的……
除了...
他们都在使用自我。关键字。
如果我的理解是正确的,这应该意味着他们总是在访问变量的实例范围版本...而不是创建自己的!
这是代码的简化版本:
import multiprocessing
import atexit
import signal
import sys
import json
class Worker(multiprocessing.Process):
def __init__(self, my_string_1, my_string_2):
# Inherit the __init_ from Process, very important or we will get errors
super(Worker, self).__init__()
# Make sure we know what to do when called to exit
atexit.register(self.exit)
signal.signal(signal.SIGTERM, self.exit)
self.my_dictionary = {
'my_string_1' : my_string_1,
'my_string_2' : my_string_2
}
def run(self):
self.my_dictionary = {
'new_string' : 'Watch me make weird stuff happen!'
}
try:
while True:
print(self.my_dictionary['my_string_1'] + " " + self.my_dictionary['my_string_2'])
except (KeyboardInterrupt, SystemExit):
self.exit()
def exit(self):
# Write the relevant data to file
info_for_file = {
'my_dictionary': self.my_dictionary
}
print(info_for_file) # For easier debugging
save_file = open('save.log', 'w')
json.dump(info_for_file, save_file)
save_file.close()
# Exit
sys.exit()
if __name__ == '__main__':
strings_list = ["Hello", "World", "Ehlo", "Wrld"]
instances = []
try:
for i in range(len(strings_list) - 2):
my_string_1 = strings_list[i]
my_string_2 = strings_list[i + 1]
instance = Worker(my_string_1, my_string_2)
instances.append(instance)
instance.start()
for instance in instances:
instance.join()
except (KeyboardInterrupt, SystemExit):
for instance in instances:
instance.exit()
instance.close()
在运行时,我们得到以下回溯...
Process Worker-2:
Process Worker-1:
Traceback (most recent call last):
File "/usr/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
self.run()
Traceback (most recent call last):
File "/usr/lib/python3.5/multiprocessing/process.py", line 249, in _bootstrap
self.run()
File "<stdin>", line 18, in run
File "<stdin>", line 18, in run
KeyError: 'my_string_1'
KeyError: 'my_string_1'
换句话说,即使在 init 期间显式添加了键 my_string_1,run() 函数仍在访问不包含该键的新版本 self.my_dictionary!
同样,如果我们处理的是普通变量(my_dictionary 而不是 self.my_dictionary),这是可以预料的,但我认为 self.variables 始终是实例范围的......
这是怎么回事?
【问题讨论】:
标签: python python-3.x class scope multiprocessing