为什么Python命令"subprocess.Popen"找不到jar文件到运行?
Why can't the Python command "subprocess.Popen" find the jar file to run?
我正在尝试 运行 来自此 repo 的代码:https://github.com/tylin/coco-caption, specifically from 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
我不明白为什么找不到文件。
我要 运行 的罐子是:
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 Python , How 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
以防万一它可能对某人有帮助:
我一直在努力解决同样的问题(相同的 https://github.com/tylin/coco-caption 代码)。可能会说我是 运行 在 CentOS 上 python 3.7 使用 qsub
的代码。所以我改变了
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 个元素的列表,一次包含带有绝对路径的整个命令。感谢您的帮助!
正如@Lars 上面提到的,我遇到的问题是我 Java 没有安装。解决方法:
sudo apt update
sudo apt install default-jdk
sudo apt install default-jre
做这个 post 因为我有两次这个问题(由于重新安装问题)并且忘了它。
我正在尝试 运行 来自此 repo 的代码:https://github.com/tylin/coco-caption, specifically from 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
我不明白为什么找不到文件。
我要 运行 的罐子是:
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 Python , How 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
因为这太复杂了试试
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
以防万一它可能对某人有帮助:
我一直在努力解决同样的问题(相同的 https://github.com/tylin/coco-caption 代码)。可能会说我是 运行 在 CentOS 上 python 3.7 使用 qsub
的代码。所以我改变了
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 个元素的列表,一次包含带有绝对路径的整个命令。感谢您的帮助!
正如@Lars 上面提到的,我遇到的问题是我 Java 没有安装。解决方法:
sudo apt update
sudo apt install default-jdk
sudo apt install default-jre
做这个 post 因为我有两次这个问题(由于重新安装问题)并且忘了它。