我试图从python中调用Java程序(Stanford Chinese Word Segmenter)。 Java程序需要加载一个大的(100M)字典文件(单词列表来辅助分割),这需要12秒以上。我想知道是否有可能加快加载过程,更重要的是,当我需要多次调用python脚本时,如何避免重复加载?
以下是代码的相关部分:
op = subprocess.Popen(['java',
'-mx2g',
'-cp',
'seg.jar',
'edu.stanford.nlp.ie.crf.CRFClassifier',
'-sighanCorporaDict',
'data',
'-testFile',
filename,
'-inputEncoding',
'utf-8',
'-sighanPostProcessing',
'true',
'ctb',
'-loadClassifier',
**'./data/ctb.gz',**
'-serDictionary',
'./data/dict-chris6.ser.gz',
'0'],
stdout = subprocess.PIPE,
stdin = subprocess.PIPE,
stderr = subprocess.STDOUT,
)
在上面的代码中,' ./ data / ctb.gz'是加载大词列表文件的位置。我认为这可能与流程有关,但我对此并不了解。
答案 0 :(得分:2)
您可以在此处使用特定于操作系统的解决方案。大多数现代操作系统都能够在内存中分区。例如,在Linux中你可以做到
mkfs -q /dev/ram1 8192
mkdir -p /ramcache
mount /dev/ram1 /ramcache
将文件移动到该目录将大大加快I / O
答案 1 :(得分:1)
可能有很多方法可以加快单词列表的加载速度,但这取决于细节。如果IO(磁盘读取速度)是瓶颈,那么一个简单的方法可能是压缩文件并使用ZipInputStream来读取它 - 但你需要对此进行基准测试。
为了避免多次加载,您可能需要保持Java进程运行,并通过文件或套接字与Python进行通信,以发送命令,而不是每次都从Python实际启动Java进程。
但是,这两个都需要修改Java代码。
答案 2 :(得分:0)
您可以运行JVM的单个实例并使用named pipes来允许python脚本与JVM通信。假设JVM执行的程序是无状态的,并且对其stdout(或许stderr)响应通过其stdin到达的请求,这将起作用。
答案 3 :(得分:0)
为什么不跟踪文件是否已在python端读取?我不是一个python高手,但我相信你可以有一些列表或地图/字典到目前为止已经打开的所有文件。
答案 4 :(得分:0)
如果java程序在收到来自filename
named pipe的输入后立即生成输出,并且您无法更改java程序,那么您可以保持Python脚本运行,并通过文件/套接字与{{{ 3}}(同样的想法,但Python程序一直在运行)。
# ...
os.mkfifo(filename)
p = Popen([..., filename, ...], stdout=PIPE)
with open(filename, 'w') as f:
while True:
indata = read_input() # read text to segment from files/sockets, etc
f.write(indata)
# read response from java process
outdata = p.stdout.readline()# you need to figure out when to stop reading
write_output(outdata) # write response via files/sockets, etc