1

在初始 Popen 解决之前使用 Popen() 启动太多进程有多大危险?

我正在对一个充满 PDF 的目录进行一些处理。我遍历每个文件并使用外部调用做两件事。

首先,我从基于 Xpdf 的 pdftohtml 工具(pdfminer 太慢)中获得了一个 html 表示。这仅输出第一页:

html = check_output(['pdftohtml.exe','-f','1','-l','1','-stdout','-noframes',pdf])

然后如果满足我的条件(我确定它是正确的文档),我会在其上调用 tabula-extractor 以提取表格。与检查文档相比,这是一个缓慢/长时间运行的过程,并且仅发生在大约 1/20 个文件上。

如果我这样做call(['jruby', 'C:\\jruby-1.7.4\\bin\\tabula', .....]),我将花费很长时间等待提取完成,同时我可以检查更多文件(我有 4 个内核和 16gb 的 ram,而 Tabula 似乎不是多线程的)。

因此,我使用 Popen() 来避免阻塞。

Popen(['jruby', 'C:\\jruby-1.7.4\\bin\\tabula', '-o', csv, '-f', 'CSV', '-a', "'",topBorder, ',', leftBorder, ',', bottomBorder, ',', rightBorder, "'", '-p', '1', pdf]) 
#where CSV is the name of the output file and pdf is the name of the input

我不关心返回值(tabula 正在创建一个 csv 文件,所以我总是可以在事后查看它是否已成功创建)。这样做意味着我可以继续在后台检查文件并根据需要启动更多的制表过程(同样,只有大约 20 分之一)。

这可行,但它会积压并最终一次运行大量的 tabula 进程。所以我的问题是:这很糟糕吗?它使计算机在其他任何事情上都变慢,但只要它不崩溃并且尽可能快地工作,我并不介意(所有 4 个内核始终处于 100%,但内存使用量不会) t 超过 5.5GB,因此它看起来受 CPU 限制)。

如果它不好,那么改善它的正确方法是什么?有没有一种方便的说法,排队 tabula 进程,所以每个核心总是有 1-2 个运行,但我不想一次处理 30 个文件?

4

1 回答 1

4

有没有一种方便的说法,排队 tabula 进程,所以每个核心总是有 1-2 个运行,但我不想一次处理 30 个文件?

是的,该multiprocessing模块就是这样做的。

import multiprocessing
import subprocess

def process_pdf(path):
    subprocess.call(['jruby', 'C:\\jruby-1.7.4\\bin\\tabula', path, ...])

pool = multiprocessing.Pool(3)      # 3 processes
results = []
for path in search_for_files():
    results.append(pool.apply_async(process_pdf, [path]))
for result in results:
    result.wait()
于 2013-09-20T21:46:52.557 回答