回答此问题可获得 20 贡献值,回答如果被采纳可获得 50 分。
<p>我正在写一些东西来静态分析不同语言的源代码。由于任何东西都必须是开源的,并且可以从命令行调用,我现在为每种语言下载了一个工具。所以我决定编写一个python脚本,列出项目文件夹中的所有源文件,并调用相应的工具。在</p>
<p>所以我的部分代码如下:</p>
<pre><code>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()
</code></pre>
<P>让我们看看C++文件部分(我使用CPPCHECK来分析这些):</P>
^{pr2}$
<p>其中一个文件(只是随机下载的文件)的控制台输出是:</p>
<pre><code>**********************************************************************
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)
</code></pre>
<p>第1行和第2行来自我的脚本,第3行到第7行来自Cppcheck。在</p>
<p>这就是我想保存到我的日志文件中的内容,对于所有其他文件也是如此。所有的东西都放在一个文件里。在</p>
<p>当然我也找过了,找到了一些方法。但没有一个是完全有效的。在</p>
<p><strong>第一次尝试:</strong></p>
<p>正在将<code>sys.stdout = open(self.logfilename, 'w')</code>添加到我的构造函数中。这使得上面显示的输出的第1行和第2行被写入日志文件。其余部分仍显示在控制台上。在</p>
<p><strong>第二次尝试:</strong></p>
<p>另外,在<code>analyseCpps</code>中,我使用:</p>
<p><code>call(['C:\CodeAnalysis\cppcheck\cppcheck', '--enable=all', sourcefile], <strong>stdout=sys.stdout</strong>)</code></p>
<p>这使我的日志文件为:</p>
<pre><code>Checking C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc...
**********************************************************************
C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc
</code></pre>
<p>控制台输出为:</p>
<pre><code>[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.
</code></pre>
<p>不是我想要的。在</p>
<p><strong>第三次尝试:</strong></p>
<p>将<code>Popen</code>与{<cd5>}一起使用。<code>sys.stdout</code>恢复为默认值。在</p>
<p>作为准备工作<code>analyseCpps</code>现在是:</p>
<pre><code>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()
</code></pre>
<p><code>p.stdout.read()</code>只显示所需输出的最后一行(代码框3中的第7行)</p>
<p><strong>第四次尝试:</strong></p>
<p>使用<code>subprocess.Popen(['C:\CodeAnalysis\cppcheck\cppcheck', '--enable=all', sourcefile], <strong>stdout=open(self.logfilename, 'a+')</strong>)</code>只需将一行<code>Checking C:\CodeAnalysis\testproject\cpp\BiggestUnInt.cc...</code>写入我的日志文件,其余的就显示在控制台上。在</p>
<p><strong>第五次尝试:</strong></p>
<p>我使用<code>subprocess.Popen</code>,而不是<code>subprocess.Popen</code>,因此我的调用命令是:</p>
<p><code>os.system('C:\CodeAnalysis\cppcheck\cppcheck --enable=all %s >> %s' % (sourcefile, self.logfilename))</code></p>
<p>这将产生与我第四次尝试相同的日志文件。如果我直接在windows控制台中输入相同的命令,结果是一样的。所以我想这并不完全是python的问题,但是:</p>
<p><strong><em>如果它在控制台上,必须有一种方法将其放入文件中。有什么想法吗?在</p>
<hr/>
<p><strong><em>电子数据</em></strong></p>
<p>愚蠢的我。我还是个笨蛋,所以我忘了<code>stderr</code>。这就是决定性的信息。在</p>
<p>所以现在我有了:</p>
<pre><code>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())
</code></pre>
<p>而且效果很好。在</p>
<hr/>
<p><strong><em>另一个编辑</em></strong></p>
<p>根据迪迪埃的回答:</p>
<p>在我的构造函数中使用<code>sys.stdout = open(self.logfilename, 'w', 0)</code>:</p>
<pre><code>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)
</code></pre>