[英]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.