python脚本使用子进程,将所有输出重定向到fi

2024-05-26 19:55:16 发布

您现在位置:Python中文网/ 问答频道 /正文

我正在写一些东西来静态分析不同语言的源代码。由于任何东西都必须是开源的,并且可以从命令行调用,我现在为每种语言下载了一个工具。所以我决定编写一个python脚本,列出项目文件夹中的所有源文件,并调用相应的工具。在

所以我的部分代码如下:

import os
import sys
import subprocess
from subprocess import call
from pylint.lint import Run as pylint


class Analyser:

    def __init__(self, source=os.getcwd(), logfilename=None):

        # doing initialization stuff
        self.logfilename = logfilename or 'CodeAnalysisReport.log'

        self.listFiles()
        self.analyseFiles()


    def listFiles(self):
    # lists all source files in the specified directory


    def analyseFiles(self):

        self.analysePythons()
        self.analyseCpps()
        self.analyseJss()
        self.analyseJavas()
        self.analyseCs()


if __name__ == '__main__':

    Analyser()

让我们看看C++文件部分(我使用CPPCHECK来分析这些):

^{pr2}$

其中一个文件(只是随机下载的文件)的控制台输出是:

**********************************************************************
C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc
Checking C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc...
[C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc:18]: (style) The scope of the variable 'oldi' can be reduced.
[C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc:43]: (style) The scope of the variable 'lastbit' can be reduced.
[C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc:44]: (style) The scope of the variable 'two_to_power_i' can be reduced.
(information) Cppcheck cannot find all the include files (use --check-config for details)

第1行和第2行来自我的脚本,第3行到第7行来自Cppcheck。在

这就是我想保存到我的日志文件中的内容,对于所有其他文件也是如此。所有的东西都放在一个文件里。在

当然我也找过了,找到了一些方法。但没有一个是完全有效的。在

第一次尝试:

正在将sys.stdout = open(self.logfilename, 'w')添加到我的构造函数中。这使得上面显示的输出的第1行和第2行被写入日志文件。其余部分仍显示在控制台上。在

第二次尝试:

另外,在analyseCpps中,我使用:

call(['C:\CodeAnalysis\cppcheck\cppcheck', '--enable=all', sourcefile], stdout=sys.stdout)

这使我的日志文件为:

Checking C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc...


********************************************************************** 
C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc

控制台输出为:

[C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc:18]: (style) The scope of the variable 'oldi' can be reduced.
[C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc:43]: (style) The scope of the variable 'lastbit' can be reduced.
[C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc:44]: (style) The scope of the variable 'two_to_power_i' can be reduced.

不是我想要的。在

第三次尝试:

Popen与{}一起使用。sys.stdout恢复为默认值。在

作为准备工作analyseCpps现在是:

for sourcefile in self.files['.cc'] + self.files['.cpp']:

    print '\n'*2, '*'*70, '\n', sourcefile
    p = subprocess.Popen(['C:\\CodeAnalysis\\cppcheck\\cppcheck', '--enable=all', sourcefile], stdout=subprocess.PIPE)
    p.stdout.read()

p.stdout.read()只显示所需输出的最后一行(代码框3中的第7行)

第四次尝试:

使用subprocess.Popen(['C:\CodeAnalysis\cppcheck\cppcheck', '--enable=all', sourcefile], stdout=open(self.logfilename, 'a+'))只需将一行Checking C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc...写入我的日志文件,其余的就显示在控制台上。在

第五次尝试:

我使用subprocess.Popen,而不是subprocess.Popen,因此我的调用命令是:

os.system('C:\CodeAnalysis\cppcheck\cppcheck --enable=all %s >> %s' % (sourcefile, self.logfilename))

这将产生与我第四次尝试相同的日志文件。如果我直接在windows控制台中输入相同的命令,结果是一样的。所以我想这并不完全是python的问题,但是:

如果它在控制台上,必须有一种方法将其放入文件中。有什么想法吗?在


电子数据

愚蠢的我。我还是个笨蛋,所以我忘了stderr。这就是决定性的信息。在

所以现在我有了:

def analyseCpps(self):

    for sourcefile in self.files['.cc'] + self.files['.cpp']:
        p = subprocess.Popen(['C:\\CodeAnalysis\\cppcheck\\cppcheck', '--enable=all', sourcefile], stderr=subprocess.PIPE)
        with open(self.logfilename, 'a+') as logfile:
            logfile.write('%s\n%s\n' % ('*'*70, sourcefile))
            for line in p.stderr.readlines():
                logfile.write('%s\n' % line.strip())

而且效果很好。在


另一个编辑

根据迪迪埃的回答:

在我的构造函数中使用sys.stdout = open(self.logfilename, 'w', 0)

def analyseCpps(self):

    for sourcefile in self.files['.cc'] + self.files['.cpp']:
        print '\n'*2, '*'*70, '\n', sourcefile
        p = subprocess.Popen(['C:\\CodeAnalysis\\cppcheck\\cppcheck', '--enable=all', sourcefile], stdout=sys.stdout, stderr=sys.stdout)

Tags: 文件theselfstdoutfilesallcppcc
3条回答

有几个问题:

  • 您应该同时重定向stdout和stderr
  • 如果要混合普通打印和已启动命令的输出,则应使用无缓冲文件。在

像这样:

import sys, subprocess

# Note the 0 here (unbuffered file)
sys.stdout = open("mylog","w",0)

print "Hello"
print "  -"

subprocess.call(["./prog"],stdout=sys.stdout, stderr=sys.stdout)
print "  -"
subprocess.call(["./prog"],stdout=sys.stdout, stderr=sys.stdout)
print "  -"

print "End"

您也需要重定向stderr,可以使用STDOUT或将file对象传递给stderr=:

from subprocess import check_call,STDOUT
with open("log.txt","w") as f:
     for sourcefile in self.files['.cc'] + self.files['.cpp']:
        check_call(['C:\\CodeAnalysis\\cppcheck\\cppcheck', ' enable=all', sourcefile],
                   stdout=f, stderr=STDOUT)

尝试将stdoutstderr重定向到日志文件:

import subprocess

def analyseCpps(self):
     with open("logfile.txt", "w") as logfile:
         for sourcefile in self.files['.cc'] + self.files['.cpp']:
             print '\n'*2, '*'*70, '\n', sourcefile
             call(['C:\\CodeAnalysis\\cppcheck\\cppcheck',
                   ' enable=all', sourcefile], stdout=logfile,
                   stderr=subprocess.STDOUT)

在本例中,文件名是硬编码的,但是您应该能够很容易地进行更改(改为您的self.logfilename或类似文件)。在

相关问题 更多 >

    热门问题