简体   繁体   English

子进程模块无法运行命令

[英]Subprocess module fails to run command

I'm trying to execute Google's cpplint.py on a group of my files and collect the results to one log file. 我正在尝试在一组文件上执行Google的cpplint.py并将结果收集到一个日志文件中。 However, I have not managed to beat the subprocess module. 但是,我还没有成功击败子进程模块。 My current code is here: 我目前的代码在这里:

import os, subprocess

rootdir = "C:/users/me/Documents/dev/"
srcdir = "project/src/"

with open(rootdir+srcdir+"log.txt", mode='w', encoding='utf-8') as logfile:
    for subdir, dirs, files in os.walk(rootdir+srcdir):
        for file in files:
            if file.endswith(".h") or file.endswith(".cpp"):
                filewithpath=os.path.join(subdir, file)
                cmd=['c:/Python27/python.exe','C:/users/me/Documents/dev/cpplint.py','--filter=-whitespace,-legal,-build/include,-build/header_guard/', filewithpath]               
                output = subprocess.check_output(cmd)
                logfile.write(output.decode('ascii'))

Trying to run the above code throws an error: 尝试运行上面的代码会引发错误:

  File "C:\Python32\lib\site.py", line 159
    file=sys.stderr)
        ^ SyntaxError: invalid syntax Traceback (most recent call last):   File "C:\Users\me\Documents\dev\project\src\verifier.py", line 19, in <module>
    output = subprocess.check_output(cmd)   File "C:\Python32\lib\subprocess.py", line 511, in check_output
    raise CalledProcessError(retcode, cmd, output=output) subprocess.CalledProcessError: Command '['c:/Python27/python.exe', 'C:/users/me/Documents/dev/cpplint.py', '--filter=-whitespace,-legal,-build/include,-build/header_guard/', 'C:/users/me/Documents/dev/project/src/aboutdialog.cpp']' returned non-zero exit status 1

If I substitute the cmd with something simpler like: 如果我用更简单的东西代替cmd:

cmd=['C:/WinAVR-20100110/bin/avr-gcc.exe','--version']

Then the script works as expected. 然后脚本按预期工作。

I have also tried to use a single command string instead of a list of strings as cmd, but the result is the same. 我也尝试使用单个命令字符串而不是字符串列表作为cmd,但结果是相同的。 When debugging the code, I copied the list-of-strings-turned-into-the-command-line-command from the debugger and ran it in the Windows command line, and the command ran as expected. 在调试代码时,我从调试器复制了list-of-strings-turned-into-the-command-line-command并在Windows命令行中运行它,命令按预期运行。

The Python interpreter running my script is Python 3.2. 运行我的脚本的Python解释器是Python 3.2。 Any tips are greatly appreciated. 任何提示都非常感谢。

Looks like cpplint.py is simply exiting with a non-zero return code - which it might do, for instance, if it finds errors or "lint" in the source files it is checking. 看起来cpplint.py只是退出非零返回代码 - 例如,如果它在它检查的源文件中发现错误或“lint”,它可能会这样做。

See the documentation for subprocess.check_output . 请参阅subprocess.check_output的文档。 Note that if the command executed returns a non-zero exit code then a subprocess.CalledProcessError is raised. 请注意,如果执行的命令返回非零退出代码,则会引发subprocess.CalledProcessError

You could work around it by watching for CalledProcessError , eg 您可以通过观察CalledProcessError解决它,例如

try:
    output = subprocess.check_output(cmd)
except subprocess.CalledProcessError as e:
    # ack!  cpplint.py failed... report an error to the user?

EDIT : 编辑

The SyntaxError seems to be the key here, and is probably caused by C:\\Python32\\lib being in your PYTHONPATH (either explicitly, or, this could happen if it is your current working directory). SyntaxError似乎是这里的关键,可能是由你的PYTHONPATH中的C:\\Python32\\lib引起的(显式,或者,如果它是你当前的工作目录,可能会发生这种情况)。

The Python interpreter (since about 1.5.2-ish) automatically runs import site when started. Python解释器(大约1.5.2-ish)在启动时自动运行import site So, when this is the case, and your script goes to execute: 因此,在这种情况下,您的脚本将执行:

c:/Python27/python.exe C:/users/me/Documents/dev/cpplint.py ...

then the Python 2.7 interpreter will find C:\\Python32\\lib\\site.py first, and try to load that, instead of the one (presumably) at C:\\Python27\\lib\\site.py . 然后Python 2.7解释器首先会找到C:\\Python32\\lib\\site.py ,并尝试加载它,而不是C:\\Python27\\lib\\site.py的那个(大概)。 The issue is that Python 3's site.py contains syntax incompatible with Python 2, so the process launched by subprocess.check_output is failing with a SyntaxError before it even gets a chance to run cpplint , which propagates the CalledProcessError . 问题是,Python 3中的site.py包含语法与Python 2不兼容,因此通过启动一个进程subprocess.check_output与一个SyntaxError失败甚至获得机会运行之前cpplint ,其传播CalledProcessError

Solution? 解? Make sure Python2 gets a bonafide Python2 "PYTHONPATH", and likewise for Python3! 确保Python2获得了真正的Python2“PYTHONPATH”,同样适用于Python3! In other words, make sure C:\\Python32\\lib is not in the PYTHONPATH search path when running the Python2 interpreter. 换句话说,运行Python2解释器时,请确保C:\\Python32\\lib不在PYTHONPATH搜索路径中。

One way to do this in your case is to set an explicit environment when launching the process, eg: 在您的情况下执行此操作的一种方法是在启动流程时设置显式环境,例如:

python2_env = {"PYTHONPATH": "path/to/python2/stuff:..."}
output = subprocess.check_output(cmd, env=python2_env)

I would request you to run this first 我会要求你先运行它

pipe = subprocess.Popen([cmd, options],stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
stdout, stderr = pipe.communicate()

You will get to know what exactly is the error behind it, since CalledProcessError is raised only if the exit code was non-zero. 您将了解其背后的错误究竟是什么,因为仅当退出代码非零时才会引发CalledProcessError。

I did it by replacing the def main() with the following (I editet the errorfunction too to get a proper csv-file): 我通过使用以下内容替换def main()来实现它(我编辑了错误函数以获得正确的csv文件):

errorlog = sys.stderr
sys.stderr = open("errorlog.csv","w")
sys.stderr.write("File;Line;Message;Category;Confidence\n")
for filename in filenames:
  ProcessFile(filename, _cpplint_state.verbose_level)
_cpplint_state.PrintErrorCounts()
sys.exit(_cpplint_state.error_count > 0)
sys.stdout = errorlog
sys.stderr.close()

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

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