为什么Python命令“subprocess.Popen”找不到要运行的jar文件?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么Python命令“subprocess.Popen”找不到要运行的jar文件?相关的知识,希望对你有一定的参考价值。

我正在尝试从这个repo运行代码:https://github.com/tylin/coco-caption,特别是来自https://github.com/tylin/coco-caption/blob/master/pycocoevalcap/tokenizer/ptbtokenizer.py,第51-52行:

p_tokenizer = subprocess.Popen(cmd, cwd=path_to_jar_dirname, 
            stdout=subprocess.PIPE)

我得到的错误是

OSError: [Errno 2] No such file or directory

我无法弄清楚为什么无法找到该文件。

我正在尝试运行的jar是:

stanford-corenlp-3.4.1.jar

你可以通过访问https://github.com/tylin/coco-caption/tree/master/pycocoevalcap/tokenizer来查看目录的结构。为了更加具体地说明当我运行代码行时我的实际参数:

cmd= ['java', '-cp', 'stanford-corenlp-3.4.1.jar', 'edu.stanford.nlp.process.PTBTokenizer', '-preserveLines', '-lowerCase', 'tmpWS5p0Z'],

path_to_dirname =abs_path_to_folder/tokenizer

我可以看到需要运行的jar,它看起来是在正确的位置,所以为什么python不能找到它。 (注意:我正在使用python2.7。)临时文件'tmpWS5p0Z'应该是它的位置。

编辑:我正在使用Ubuntu

答案

尝试绝对路径(意思是从根/开始的路径)

https://en.wikipedia.org/wiki/Path_(computing)#Absolute_and_relative_paths

对于python中的相对路径,请参阅Relative paths in PythonHow to refer to relative paths of resources when working with a code repository in Python

更新:

作为测试尝试subprocess.Popen()shell=True选项,并为任何涉及的文件提供绝对路径,包括tmpWS5p0Z

在这个subprocess.Popen()电话涉及两条路径:

1)python路径,python必须找到java可执行文件和stanford-corenlp-3.4.1.jar,它本质上是一个带有自己路径的java程序

2)stanford-corenlp-3.4.1.jar的java路径

因为这太复杂了尝试

p_tokenizer = subprocess.Popen(['/absolute_path_to/java -cp /absolute_path_to/stanford-corenlp-3.4.1.jar /absolute_path_to/edu.stanford.nlp.process.PTBTokenizer -preserveLines -lowerCase /absolute_path_to/tmpWS5p0Z' ], shell=True)

Python specify popen working directory via argument

Python subprocess.Popen() error (No such file or directory)

另一答案

以防万一它可以帮助某人:

我正在努力解决同样的问题(同样的https://github.com/tylin/coco-caption代码)。可能与我说使用qsub在CentOS上使用python 3.7运行代码有关。所以我改变了

cmd = ['java', '-cp', 'stanford-corenlp-3.4.1.jar', 'edu.stanford.nlp.process.PTBTokenizer', '-preserveLines', '-lowerCase', 'tmpWS5p0Z']

cmd = ['/abs/path/to/java -cp /abs/path/to/stanford-corenlp-3.4.1.jar edu.stanford.nlp.process.PTBTokenizer -preserveLines -lowerCase ', ' /abs/path/to/temporary_file']

使用绝对路径固定OSError: [Errno 2] No such file or directory。请注意,我仍然将'/abs/path/to/temporary_file'作为cmd列表中的第二个元素,因为它稍后添加了。但是后来在tokenizer java子进程中出现了问题,我不知道为什么或者是什么,只是观察因为:

p_tokenizer = subprocess.Popen(cmd, cwd=path_to_jar_dirname, stdout=subprocess.PIPE, shell=True)
token_lines = p_tokenizer.communicate(input=sentences.rstrip())[0]

这里token_lines是一个空列表(这不是想要的行为)。在IPython中执行此操作导致以下(只是subprocess.Popen(...,而不是communicate)。

Exception in thread "main" edu.stanford.nlp.io.RuntimeIOException: java.io.IOException: Input/output error
    at edu.stanford.nlp.process.PTBTokenizer.getNext(PTBTokenizer.java:278)
    at edu.stanford.nlp.process.PTBTokenizer.getNext(PTBTokenizer.java:163)
    at edu.stanford.nlp.process.AbstractTokenizer.hasNext(AbstractTokenizer.java:55)
    at edu.stanford.nlp.process.PTBTokenizer.tokReader(PTBTokenizer.java:444)
    at edu.stanford.nlp.process.PTBTokenizer.tok(PTBTokenizer.java:416)
        at edu.stanford.nlp.process.PTBTokenizer.main(PTBTokenizer.java:760)
Caused by: java.io.IOException: Input/output error
    at java.base/java.io.FileInputStream.readBytes(Native Method)
    at java.base/java.io.FileInputStream.read(FileInputStream.java:279)
    at java.base/java.io.BufferedInputStream.read1(BufferedInputStream.java:290)
    at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:351)
    at java.base/sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
    at java.base/sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
    at java.base/sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
    at java.base/java.io.InputStreamReader.read(InputStreamReader.java:185)
    at java.base/java.io.BufferedReader.read1(BufferedReader.java:210)
    at java.base/java.io.BufferedReader.read(BufferedReader.java:287)
    at edu.stanford.nlp.process.PTBLexer.zzRefill(PTBLexer.java:24511)
    at edu.stanford.nlp.process.PTBLexer.next(PTBLexer.java:24718)
    at edu.stanford.nlp.process.PTBTokenizer.getNext(PTBTokenizer.java:276)
    ... 5 more

再一次,我不知道为什么或什么,但我只想分享这样做,修复它:

cmd = ['/abs/path/to/java -cp /abs/path/to/stanford-corenlp-3.4.1.jar edu.stanford.nlp.process.PTBTokenizer -preserveLines -lowerCase /abs/path/to/temporary_file']

并将cmd.append(os.path.join(path_to_jar_dirname, os.path.basename(tmp_file.name)))改为cmd[0] += os.path.join(path_to_jar_dirname, os.path.basename(tmp_file.name))

因此,将cmd放入只包含1个元素的列表中,同时包含具有绝对路径的整个命令。谢谢你的帮助!

以上是关于为什么Python命令“subprocess.Popen”找不到要运行的jar文件?的主要内容,如果未能解决你的问题,请参考以下文章

Python:当父进程死亡时如何杀死子进程?

网络编程 --ftp上传

subprocess.Popen("echo $HOME"... 和 subprocess.Popen(["echo", "$HOME"]

pytesseract.pytesseract.TesseractNotFoundError: tesseract is not installed or it's not in your p

为什么python无法读取环境变量并且无法运行Windows命令行?

什么是“th”、“python”、“python3”、“java”等等……前面用来运行脚本的命令,叫什么?