我有一个可执行文件,需要使用不同的参数经常运行。为此,我按照此处给出的模式,使用多处理模块编写了一个小的Python(2.7)包装器。
我的代码如下所示:
try:
logging.info("starting pool runs")
pool.map(run_nlin, params)
pool.close()
except KeyboardInterrupt:
logging.info("^C pressed")
pool.terminate()
except Exception, e:
logging.info("exception caught: ", e)
pool.terminate()
finally:
time.sleep(5)
pool.join()
logging.info("done")
我的工作者函数在这里:
class KeyboardInterruptError(Exception): pass
def run_nlin((path_config, path_log, path_nlin, update_method)):
try:
with open(path_log, "w") as log_:
cmdline = [path_nlin, path_config]
if update_method:
cmdline += [update_method, ]
sp.call(cmdline, stdout=log_, stderr=log_)
except KeyboardInterrupt:
time.sleep(5)
raise KeyboardInterruptError()
except:
raise
path_config
是二进制程序的配置文件的路径;例如,有运行该程序的日期。
当我启动包装器时,一切看起来都很好。但是,当我按时^C
,包装脚本似乎numproc
在终止之前从池中启动了其他进程。例如,当我在1-10天启动脚本时,在psaux
输出中可以看到二进制程序的两个实例正在运行(通常在1天和3天)。现在,当我按时^C
,包装脚本退出,第1天和第3天的二进制程序消失了,但是第5天和第7天又有新的二进制程序运行了。
因此对我来说,似乎在最终死亡之前Pool
启动了另一个numproc
进程。
有什么想法在这里发生什么,我能做些什么?
在此页面上,多处理模块的作者Jesse Noller显示正确的处理方式KeyboardInterrupt
是让子流程返回-
不会引发异常。这允许主进程终止池。
但是,如下面的代码所示,except KeyboardInterrupt
直到运行了由生成的所有任务 之后
,主流程才到达该块pool.map
。这就是为什么(我相信)在按下run_nlin
后会看到对辅助函数的额外调用Ctrl-C
。
一种可能的解决方法是,如果multiprocessing.Event
设置了a,则对所有工作程序功能进行测试。如果事件已发生,则请工人提早纾困,否则,请继续进行长时间的计算。
import logging
import multiprocessing as mp
import time
logger = mp.log_to_stderr(logging.WARNING)
def worker(x):
try:
if not terminating.is_set():
logger.warn("Running worker({x!r})".format(x = x))
time.sleep(3)
else:
logger.warn("got the message... we're terminating!")
except KeyboardInterrupt:
logger.warn("terminating is set")
terminating.set()
return x
def initializer(terminating_):
# This places terminating in the global namespace of the worker subprocesses.
# This allows the worker function to access `terminating` even though it is
# not passed as an argument to the function.
global terminating
terminating = terminating_
def main():
terminating = mp.Event()
result = []
pool = mp.Pool(initializer=initializer, initargs=(terminating, ))
params = range(12)
try:
logger.warn("starting pool runs")
result = pool.map(worker, params)
pool.close()
except KeyboardInterrupt:
logger.warn("^C pressed")
pool.terminate()
finally:
pool.join()
logger.warn('done: {r}'.format(r = result))
if __name__ == '__main__':
main()
运行脚本将产生:
% test.py
[WARNING/MainProcess] starting pool runs
[WARNING/PoolWorker-1] Running worker(0)
[WARNING/PoolWorker-2] Running worker(1)
[WARNING/PoolWorker-3] Running worker(2)
[WARNING/PoolWorker-4] Running worker(3)
在这里按Ctrl-C;每个工人都设置terminating
事件。我们确实只需要设置它,但是尽管效率很低,但它仍然有效。
C-c C-c[WARNING/PoolWorker-4] terminating is set
[WARNING/PoolWorker-2] terminating is set
[WARNING/PoolWorker-3] terminating is set
[WARNING/PoolWorker-1] terminating is set
现在,所有其他排队的任务pool.map
都将运行:
[WARNING/PoolWorker-4] got the message... we're terminating!
[WARNING/PoolWorker-2] got the message... we're terminating!
[WARNING/PoolWorker-1] got the message... we're terminating!
[WARNING/PoolWorker-2] got the message... we're terminating!
[WARNING/PoolWorker-4] got the message... we're terminating!
[WARNING/PoolWorker-2] got the message... we're terminating!
[WARNING/PoolWorker-1] got the message... we're terminating!
[WARNING/PoolWorker-3] got the message... we're terminating!
最终,主要过程到达except KeyboardInterrupt
块。
[WARNING/MainProcess] ^C pressed
[WARNING/MainProcess] done: []
假设有一个SessionFactory的生产者(举个例子): 不,我可以这样使用我的数据库对象: 到目前为止,一切都很好。因此,让我们假设这些东西是在一个框架中实现的,并且将被几个应用程序使用。 现在,一个应用程序决定使用另一个SessionFactory,因此它实现了自己的生产者和一个限定符:
我是Prisma的新手,我喜欢使用它。 显然,我一直在使用MySQL开发目的创建演示服务器。然而,当我尝试更新prisma.yml文件以生成Prisma图ql模式文件时,我发现有几种方法可以做到这一点。 首先,在yml文件中使用属性,如下所示: 第二种方法是使用hook方法: 因此,我在想,这两种方法中哪一种更适合goto方法,这两种方法的不同用例是什么? 成果 在使用generate方法时,我注
问题内容: 我正在使用JPA(EclipseLink)和Spring。假设我有一个带有自动生成的ID的简单实体: 在我的DAO类中,我有一个调用此实体的insert方法。我希望该方法为新实体返回生成的ID,但是当我对其进行测试时,它将返回。 我还有一个包装DAO的服务类,如果有区别的话: 问题答案: 该ID仅保证在刷新时生成。持久实体只会使它“附加”到持久性上下文。因此,要么显式刷新实体管理器:
在创建项目时更新android studio后,我收到一个错误: 错误:任务“:app:preDebugAndroidTestBuild”的执行失败。与依赖项com冲突。Android支持:支持注释“在项目中”:应用程序。app(26.1.0)和测试app(27.1.1)的解析版本有所不同。看见https://d.android.com/r/tools/test-apk-dependency-co
问题内容: 这似乎是一个基本问题,但是我找不到任何文档: 分叉和生成node.js进程有什么区别?我已经读过分叉是生成的一种特殊情况,但是使用它们的不同用例/重用分别是什么? 问题答案: Spawn是用于运行系统命令的命令。运行spawn时,会向其发送系统命令,该命令将在其自己的进程上运行,但不会在节点进程内执行任何其他代码。您可以为生成的进程添加侦听器,以允许您的代码与生成的进程进行交互,但是不
问题内容: 在Firefox 3和Google Chrome 8.0中,以下功能可以正常运行: 但是当元素为时不是这样: 为什么它不按我的预期工作? 问题答案: 使用和指定要在该元素内部 的内容 之前(或之后)插入 的内容 。元素没有内容。 例如,如果你写的(这是错误的),浏览器会纠正这一点,并把文字 后 输入元素。 您唯一可以做的就是将每个输入元素包装在span或div中,并在这些元素上应用CS