[英]Multiprocessing and matlibplot, non-blocking plots
我知道关于这个主题还有很多其他问题,我已经阅读/试验了这些解决方案,但没有一个完全符合我的要求或不工作......
我想做什么:
我想使用 matplotlib 创建一个绘图,该绘图在一个新进程中启动,以便在主线程运行时它是开放的并具有响应性,另外当主线程退出时不会杀死子进程。 如果可能的话,我想要一些便携的东西,因此我一直避免使用 fork,因为我的印象是它不是(正确的?)。 我在 matplotlib 中尝试过 show(block=False)。 如果没有其他任何东西,我很乐意接受,但最好是主线程退出并且情节仍在那里。
到目前为止我最好的尝试:
此代码是在关闭主进程时从Python close children修改的
import logging, signal, sys, time
import multiprocessing as mp
import matplotlib.pyplot as plt
from mpl_toolkits.axes_grid.axislines import SubplotZero
class AddProcessNameFilter(logging.Filter):
"""Add missing on Python 2.4 `record.processName` attribute."""
def filter(self, r):
r.processName = getattr(r, 'processName', mp.current_process().name)
return logging.Filter.filter(self, r)
def print_dot(plt):
signal.signal(signal.SIGTERM, signal.SIG_IGN)
while True:
mp.get_logger().info(".")
plt.show(block=True)
def main():
logger = mp.log_to_stderr()
logger.setLevel(logging.INFO)
logger.addFilter(AddProcessNameFilter()) # fix logging records
fig = plt.figure()
ax = fig.add_subplot(111)
ax.plot([0, 1, 2, 3], [1, 1, 3, 2],'ro')
# create daemonic child processes
p = mp.Process(target=print_dot, args=(plt,))
p.daemon = True
p.start()
if __name__=="__main__":
mp.freeze_support()
main()
这段代码会发生什么......
情节不会另外启动,主线程不会退出它只是等待加入。 中断时,我也会收到以下错误...
X Error of failed request: BadIDChoice (invalid resource ID chosen for this connection)
Major opcode of failed request: 53 (X_CreatePixmap)
Resource id in failed request: 0x4400017
Serial number of failed request: 344
Current serial number in output stream: 352
不太确定该怎么做。 有任何想法吗? 提前致谢
PS:Ubuntu 12.04 ......但我不知道这在这种情况下是否特别相关......
我使用以下代码。 它与您的类似,但加入了旧进程,因为该函数应该被多次调用。 你可以关闭主进程,情节不会被关闭。
不能保证在调用 p.start 后会立即显示该图。 但这将是非常不寻常的,并且只发生在我身上几次。 在这些时候,如果再次调用 plot 或者我调用 p.is_alive(),则会显示窗口。
import multiprocessing as mp
import sys
def foo(*arg):
import matplotlib.pyplot as plt
plt.ioff()
plt.plot(*arg)
plt.show()
if __name__ == '__main__':
mp.freeze_support()
arg=(range(10),)
global pl
#create the process list, if it does not exists
try:
pl
except NameError:
pl = []
#Join old ones to keep zombie process list small
for i in range(len(pl)):
if not (pl[i] is None):
if not pl[i].is_alive():
pl.pop(i).join()
#create plot process
p = mp.Process(target=foo, args=arg)
p.start()
pl.append(p)
我推荐来自https://stackoverflow.com/a/62354049/13995577的解决方案。 对我来说效果很好。 虽然它有点黑客,但相对较小。
import multiprocessing as mp
def my_plot_routine(q):
...
q.put('Done, see plot window')
plt.show()
return
class EverLastingProcess(mp.Process):
def join(self, *args, **kwargs):
pass
def __del__(self):
pass
if __name__ == '__main__':
# create plot process
mp.set_start_method('spawn')
q = mp.Queue()
p = EverLastingProcess(target=my_plot_routine, args=(q,))
p.start()
print(q.get())
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.