【问题标题】:Why can't the Python command "subprocess.Popen" find the jar file to run?为什么Python命令“subprocess.Popen”找不到要运行的jar文件?
【发布时间】:2018-03-14 00:12:45
【问题描述】:

我正在尝试从这个 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

【问题讨论】:

    标签: python python-2.7 jar subprocess popen


    【解决方案1】:

    以防万一它可能对某人有所帮助:

    我正在努力解决同样的问题(相同的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 个元素的列表,同时包含带有绝对路径的整个命令。感谢您的帮助!

    【讨论】:

    • 你的临时文件在哪里?
    • 和 stanford-corenlp-3.4.1.jar 在同一个目录下 :) 所以在 coco-caption/pycocoevalcap/tokenizer/
    【解决方案2】:

    尝试绝对路径(即从根/开始的路径)

    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

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

    【讨论】:

    • 我已经更新了我的问题,但我的 path_to_dirname 已经在绝对路径上。更新了问题以反映这一点。
    • 谢谢,您的回答有帮助。基本上,问题是我假设我正在使用的计算机安装了 java。它没有。
    • 根是/,而不是`\`
    • 你的临时文件在哪里?
    【解决方案3】:

    正如@Lars 上面提到的,我遇到的问题是我没有安装 Java。解决了:

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

    由于我两次遇到此问题(由于重新安装问题)并忘记了它,所以发布此帖子。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-02
      • 2018-01-24
      • 2013-08-11
      • 2013-11-13
      • 2021-11-30
      • 1970-01-01
      • 2016-04-26
      • 1970-01-01
      相关资源
      最近更新 更多