简体   繁体   English

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

[英]Why can't the Python command "subprocess.Popen" find the jar file to run?

I'm trying to run code from this repo: https://github.com/tylin/coco-caption , specifically from https://github.com/tylin/coco-caption/blob/master/pycocoevalcap/tokenizer/ptbtokenizer.py , line 51-52:我正在尝试从这个 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)

The error I get running this is我运行的错误是

OSError: [Errno 2] No such file or directory

I can't figure out why the file can't be found.我无法弄清楚为什么找不到该文件。

The jar I'm trying to run is:我试图运行的罐子是:

stanford-corenlp-3.4.1.jar

You can see the structure of directory by going to https://github.com/tylin/coco-caption/tree/master/pycocoevalcap/tokenizer .您可以通过转到https://github.com/tylin/coco-caption/tree/master/pycocoevalcap/tokenizer查看目录结构。 For more specificity into what my actual arguments are when I run the line of code:当我运行代码行时,为了更具体地了解我的实际参数是什么:

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

and

path_to_dirname =abs_path_to_folder/tokenizer

I can see the jar that needs to be run, and it looks to be in the right place, so why can't python find it.我可以看到需要运行的jar,而且它看起来在正确的位置,为什么python找不到它。 (Note: I'm using python2.7.) And the temporary File 'tmpWS5p0Z' is where it should be. (注意:我使用的是 python2.7。)临时文件 'tmpWS5p0Z' 是它应该在的位置。

Edit: I'm using Ubuntu编辑:我正在使用 Ubuntu

Just in case it might help someone:以防万一它可能对某人有所帮助:

I was struggling with the same problem (same https://github.com/tylin/coco-caption code).我正在努力解决同样的问题(相同的https://github.com/tylin/coco-caption代码)。 Might be relevant to say that I was running the code with python 3.7 on CentOS using qsub .可以说我在 CentOS 上使用qsub运行带有 python 3.7 的代码。 So I changed所以我改变了

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

to

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']

Using absolute paths fixed the OSError: [Errno 2] No such file or directory .使用绝对路径修复了OSError: [Errno 2] No such file or directory Notice that I still put '/abs/path/to/temporary_file' as second element in the cmd list, because it got added later on.请注意,我仍然将'/abs/path/to/temporary_file'作为cmd列表中的第二个元素,因为它是稍后添加的。 But then something went wrong in the tokenizer java subprocess, I don't know why or what, just observing because:但是后来在标记器 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]

Here token_lines was an empty list (which is not the wanted behavior).这里token_lines是一个空列表(这不是想要的行为)。 Executing this in IPython resulted in the following (just the subprocess.Popen(... , not the communicate ).在 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

Again, I don't know why or what, but I just wanted to share that doing this fixed it:同样,我不知道为什么或什么,但我只是想分享一下,这样做修复了它:

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']

And changing cmd.append(os.path.join(path_to_jar_dirname, os.path.basename(tmp_file.name))) into cmd[0] += os.path.join(path_to_jar_dirname, os.path.basename(tmp_file.name)) .并将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))

So making cmd into a list with only 1 element, containing the entire command with absolute paths at once.所以将cmd变成一个只有 1 个元素的列表,一次包含整个命令和绝对路径。 Thanks for your help!谢谢你的帮助!

try an absolute path ( meaning the path beginning from root / )尝试绝对路径(意思是从根/开始的路径)

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

for relative paths in python see ie Relative paths in Python , How to refer to relative paths of resources when working with a code repository in Python对于 Python 中的相对路径,请参见 ie Python 中的相对路径如何在 Python 中使用代码存储库时引用资源的相对路径

UPDATE:更新:

As a test try subprocess.Popen() with the shell=True option and give an absolute path for any involved file, including tmpWS5p0Z作为测试,使用shell=True选项尝试subprocess.Popen()并为任何涉及的文件提供绝对路径,包括tmpWS5p0Z

in this subprocess.Popen() call are involved two paths :在这个subprocess.Popen()调用中涉及两条路径:

1) the python path, python has to find the java executable and the stanford-corenlp-3.4.1.jar which is essentially a java program with its own path 1)python路径,python必须找到java可执行文件和stanford-corenlp-3.4.1.jar ,它本质上是一个有自己路径的java程序

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

as this is all too complicated try因为这太复杂了尝试

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 通过参数指定 popen 工作目录

Python subprocess.Popen() error (No such file or directory) Python subprocess.Popen() 错误(没有那个文件或目录)

As @Lars mentioned above the issue I had was that I Java wasn't installed.正如@Lars 上面提到的,我遇到的问题是我没有安装 Java。 Solved it with:解决了它:

sudo apt update    
sudo apt install default-jdk
sudo apt install default-jre

Making this post since I had this issue twice (due to reinstallation problems) and forgot about it.发表这篇文章是因为我两次遇到这个问题(由于重新安装问题)并忘记了它。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM