Python:在文件更改时将文件打印到流

2024-04-25 22:41:40 发布

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

我正在通过另一个应用程序(Autodesk Maya)在子进程中运行大型单元测试套件。Maya运行一个特殊的Python解释器,它自己的库不能在应用程序之外使用,因此需要在应用程序中进行测试。我希望父进程打印测试结果,因为它正在发生。但是子进程非常“嘈杂”,所以我不想简单地将子进程的stdout重定向到父进程的stdout。相反,我希望测试运行程序以某种方式直接流到父进程的stdout

我目前正在子进程中使用TextTestRunner,它的stdout设置为一个打开的文件。父进程知道该文件的位置,并在子进程完成后将tile的内容写入stdout。但是,由于测试可能需要很长时间才能运行,所以我希望父进程能够在子进程创建该文件时以某种方式“流化”该文件的内容。但我不知道该怎么做,也不知道是否有更好的方法。在

下面是一个当前如何设置的示例。在

module_path = 'my.test.module'
suite_callable = 'suite'
stream_fpath = '/tmp/the_test_results.txt'
script_fpath = '/tmp/the_test_script.py'
script = '''
import sys
if sys.version_info[0] <= 2 and sys.version_info[1] <= 6:
    import unittest2 as unittest
else:
    import unittest

import {module_path}
suite = {module_path}.{suite_callable}()
with open("{stream_path}", "w") as output:
    runner = unittest.TextTestRunner(stream=output)
    runner.run(suite)
    output.close()

'''.format(**locals())

with open(script_fpath, 'w') as f:
    f.write(script)
subprocess.call(['maya', '-command', '\'python("execfile(\\"{script_fpath}\\")")\''.format(**locals())]
with open(stream_fpath, 'r') as f:
    print f.read()

谢谢你的任何信息!在


Tags: 文件pathtestimport应用程序stream进程as
2条回答

(已编辑-建议使用stderr或解析)

备选方案1:截取输出而不是将其放入文件。在

script写入sys.stderr,而不是stream_fpath的{}:

runner = unittest.TextTestRunner(stream=sys.stderr)

subprocess.call替换为running = subprocess.Popen(<existing parameters>, stderr=PIPE)。然后读取running.stderr,直到EOF或直到running.poll()返回None以外的值。你可以对数据做你想做的事。例如,您可以将其打印到屏幕上,也可以将其打印到stream_fpath。在

这假设噪声输出来自maya,它仍将转储到stdout。在

备选方案2:解析来自stdout=PIPE的噪声输出。如果可以通过向每行添加一些标记来区分测试运行器的输出,则可以搜索该标记并只打印匹配的行。在

Popen documentation (Python 2)

您应该能够生成一个file-like object来替换stderr,而不是写入一个文件。对象的write方法可以在输入时对每个输入执行某些操作;您可以将它喷射到TCP上侦听的内容,或将内容打印到TK窗口,或者除了记录到文件之外的任何其他操作(如果您仍然需要结果)。在

实现流替换非常简单,在这种情况下,您可能只需要实现write、writeline、open和close(除非testrunner也使用flush)。在

class FakeStdErr(object):
     def __init__(self)
         self.lines = []

     def write(self, text):
         self.lines.append(text)

    def writelines(self, *args):
         for item in args: self.lines.append(item)

    def open(self):
        self.lines = []

    def close (self):
        pass

在您的用例中,您可能希望使用一个silencer class(这是一个相同技巧的变体)来替换默认的stdout(关闭您的chatty进程),并将您的测试运行程序流指向这个人;所有测试完成后,您可以将内容作为文件转储到磁盘上,或者通过恢复默认的stdout将其打印到屏幕上(如果您不熟悉,该链接将显示如何执行此操作)。在

相关问题 更多 >

    热门问题