Python: 在另一个进程中通过id获取对象
Python: Get object by id in another process
问题
我正在制作多处理块生成器,但我无法通过子进程的 ID 获取对象。我在 Windows 10.
代码
import _ctypes
import classes as pycraft
import multiprocessing
def start_generaion(window):
# We don't have to worry about infinite loops, because
# this is going to be run in another thread, using popen.
try:
world = _ctypes.PyObj_FromPtr(window).model
print(world, flush=True)
while True:
for i in world._queue:
world.all_chunks[i].generate()
except Exception as e:
print(f'Error in world generation process. \n{e}', flush=True)
if __name__ == '__main__':
world = pycraft.world()
world = id(world)
world_gen_process = multiprocessing.Process(target = start_generaion, args = (world,))
world_gen_process.start()
提前致谢!
以下代码将常规对象的 ID 传递给另一个进程,它能够从 Linux 下的 ID 成功恢复对象:
import _ctypes
import multiprocessing
import sys
def foo(id1, label):
try:
print(label, id1)
v = _ctypes.PyObj_FromPtr(id1)
print(v)
except:
print("Unexpected error:", sys.exc_info()[0])
finally:
print('finally')
if __name__ == '__main__':
d = {'a': 1}
id1 = id(d)
foo(id1, 'Main process id:')
p = multiprocessing.Process(target=foo, args=(id1, 'Subprocess id:'))
p.start()
p.join()
打印:
Main process id: 140443371291200
{'a': 1}
finally
Subprocess id: 140443371291200
{'a': 1}
finally
但是在Windows下运行时,输出的都是:
Main process id: 1687385043136
{'a': 1}
finally
Subprocess id: 1687385043136
子进程在没有执行我无法解释的 except
或 finally
块的情况下突然终止。
问题在于,当使用 spawn 方法创建新进程时,就像 Windows 的情况一样,该进程不会从主进程继承任何内容。相反,会创建一个新地址 space,并在该 space 中启动一个 Python 解释器,并重新读取源文件,在全局范围内执行所有内容,作为初始化内存的方式,为调用工作函数(在我的示例中为 foo
)。但是变量,在新地址中不会有相同的地址 space 除非是最大的巧合。
您没有说明您 运行 正在使用哪个平台,但我强烈怀疑它使用 spawn 来创建新进程。 但即使在 Linux 下,虽然您能够重新创建对象引用,但它实际上只是原始对象的副本(技术上涉及写时复制语义,但一旦引用计数为对象增加,这将导致制作实际副本)。
问题
我正在制作多处理块生成器,但我无法通过子进程的 ID 获取对象。我在 Windows 10.
代码
import _ctypes
import classes as pycraft
import multiprocessing
def start_generaion(window):
# We don't have to worry about infinite loops, because
# this is going to be run in another thread, using popen.
try:
world = _ctypes.PyObj_FromPtr(window).model
print(world, flush=True)
while True:
for i in world._queue:
world.all_chunks[i].generate()
except Exception as e:
print(f'Error in world generation process. \n{e}', flush=True)
if __name__ == '__main__':
world = pycraft.world()
world = id(world)
world_gen_process = multiprocessing.Process(target = start_generaion, args = (world,))
world_gen_process.start()
提前致谢!
以下代码将常规对象的 ID 传递给另一个进程,它能够从 Linux 下的 ID 成功恢复对象:
import _ctypes
import multiprocessing
import sys
def foo(id1, label):
try:
print(label, id1)
v = _ctypes.PyObj_FromPtr(id1)
print(v)
except:
print("Unexpected error:", sys.exc_info()[0])
finally:
print('finally')
if __name__ == '__main__':
d = {'a': 1}
id1 = id(d)
foo(id1, 'Main process id:')
p = multiprocessing.Process(target=foo, args=(id1, 'Subprocess id:'))
p.start()
p.join()
打印:
Main process id: 140443371291200
{'a': 1}
finally
Subprocess id: 140443371291200
{'a': 1}
finally
但是在Windows下运行时,输出的都是:
Main process id: 1687385043136
{'a': 1}
finally
Subprocess id: 1687385043136
子进程在没有执行我无法解释的 except
或 finally
块的情况下突然终止。
问题在于,当使用 spawn 方法创建新进程时,就像 Windows 的情况一样,该进程不会从主进程继承任何内容。相反,会创建一个新地址 space,并在该 space 中启动一个 Python 解释器,并重新读取源文件,在全局范围内执行所有内容,作为初始化内存的方式,为调用工作函数(在我的示例中为 foo
)。但是变量,在新地址中不会有相同的地址 space 除非是最大的巧合。
您没有说明您 运行 正在使用哪个平台,但我强烈怀疑它使用 spawn 来创建新进程。 但即使在 Linux 下,虽然您能够重新创建对象引用,但它实际上只是原始对象的副本(技术上涉及写时复制语义,但一旦引用计数为对象增加,这将导致制作实际副本)。