Python 和多进程... 如何在主进程中调用函数?

3 投票
2 回答
4377 浏览
提问于 2025-04-16 13:05

我想在Python中实现一个异步回调风格的函数……这是我想到的,但我不太确定怎么才能回到主进程并调用这个函数。

funcs = {} 

def runCallback(uniqueId):
    '''
    I want this to be run in the main process.
    '''
    funcs[uniqueId]()


def someFunc(delay, uniqueId):
    '''
    This function runs in a seperate process and just sleeps.  
    '''
    time.sleep(delay)

    ### HERE I WANT TO CALL runCallback IN THE MAIN PROCESS ###

    # This does not work... It calls runCallback in the separate process:
    runCallback(uniqueId)


def setupCallback(func, delay):
    uniqueId = id(func)
    funcs[uniqueId] = func
    proc = multiprocessing.Process(target=func, args=(delay, uniqueId))
    proc.start()
    return unqiueId

这是我希望它工作的方式:

def aFunc():
    return None

setupCallback(aFunc, 10)
### some code that gets run before aFunc is called ###
### aFunc runs 10s later ###

这里有个小问题,因为我想让这个功能稍微复杂一些。基本上,当主进程的代码运行完毕后……我想检查一下funcs字典,然后运行那些还没有执行的回调。这就意味着runCallback也需要从funcs字典中删除一些条目……而且funcs字典并不是和其他进程共享的,所以我觉得runCallback需要在主进程中被调用???

2 个回答

4

要实现你想要的功能,你需要在父进程中设置一个信号处理器,这样它就可以运行回调函数(或者如果子进程不需要访问父进程的内存,可以直接去掉子进程运行的回调函数)。然后让子进程发送一个信号。不过,如果你的逻辑变得更复杂,你可能需要使用其他的进程间通信方式,比如管道或者套接字

另一种选择是使用线程而不是进程,这样你就可以直接在第二个线程中运行回调函数。你需要添加一个来同步对funcs字典的访问。

4

不太明白你为什么在这里使用 multiprocessing 模块。

如果你想在同一个进程中延迟调用一个函数,可以使用 threading.Timer

threading.Timer(10, aFunc).start()

Timer 有一个 .cancel() 方法,如果你想稍后取消这个回调的话,可以用这个方法:

t = threading.Timer(10, runCallback, args=[uniqueId, funcs])
t.start()
timers.append((t, uniqueId))
# do other stuff
# ...
# run callbacks right now
for t, uniqueId in timers:
    t.cancel() # after this the `runCallback()` won't be called by Timer()
               # if it's not been called already
    runCallback(uniqueId, funcs)

在这里,runCallback() 被修改过,以便移除要调用的函数:

def runCallback(uniqueId, funcs):
    f = funcs.pop(uniqueId, None) # GIL protects this code with some caveats
    if f is not None:
       f()

撰写回答