我正在为Python构建一个库,并注意到我的一个用户通过在2个进程之间共享对象而错误地使用了对象。
所以,我想用某种方式烘烤,以防止用户这样做。
一种方法是在每个方法调用之前使用装饰器添加一个“检查”,但这会在每个方法调用上增加一些开销。
import multiprocessing
import threading
def is_parent():
return (
multiprocessing.current_process().name == "MainProcess"
and threading.current_thread() == threading.main_thread()
)
def process_unsafe(fn):
def wrapper(*args, **kwargs):
if not is_parent():
raise RuntimeError("Not allowed!")
fn(*args, **kwargs)
return wrapper
class NonProcessSafe:
@process_unsafe
def foo(self):
pass
@process_unsafe
def bar(self):
pass
nps = NonProcessSafe()
nps.foo()
nps.bar()
def child():
# complains
nps.foo()
p = multiprocessing.Process(target=child)
p.start()
p.join()
有没有更有效的方法来实现这一目标?
答案 0 :(得分:0)
正如@timgeb在评论中提到的那样,可能无法消除所有漏洞。此外,我不确定我是否完全了解您的问题以及进程/线程/状态共享模型...
无论如何,至少在处理方面(在Unix / Linux方面),这是一个Ansatz可能会带您到某个地方:
import os
class State:
def __init__(self):
self._pid = os.getpid()
self._state = {}
def __setitem__(self, key, value):
if os.getpid() != self._pid:
raise RuntimeError("this process must not change state")
self._state[key] = value
State
实例会记住创建它的进程的ID,然后可以在所有(相关)方法中对该ID进行检查。当然,这将需要通过其“所有者”过程创建国家,在这种情况下,任何父母或兄弟姐妹过程都不会看到它,并且仅对其本国及其子代可见。
对于线程,请使用threading.get_ident()
而不是os.getpid()
。
如果总是由“主”进程创建状态,然后派生工作人员子进程,则可以(在主进程中)暂时将状态标记为只读,请分叉工作人员子进程,使其获得只读权限-仅复制,然后在主进程切换状态下恢复为读写状态:
class State:
def __init__(self):
self._read_only = False
self._state = {}
def __setattr__(self, key, value):
if self._read_only:
raise RuntimeError("read only!")
self._state[key] = value
在主要过程中:
def new_worker(fct):
state = State()
state._read_only = True
pid = os.fork() # or whatever you use to create a new process
if pid:
fct() # state is _read-only=True here in child process
else:
state._read_only = False
state_list.append((pid, state))