Python unittest打印日志记录适用于Linux,但不适用于Windows

时间:2014-01-07 19:43:01

标签: python windows unittest++

我正在尝试编写一个将stdout和stderr重定向到Windows网络驱动器上写入的文件的unittest。出于某种原因,相同的脚本(只有diff。是目录路径)适用于Linux,但不适用于Windows。在Windows上运行时,不会将任何内容写入日志文件。

以下是Windows上的脚本,没有任何内容可写:

import sys
import unittest

LOGDIR = r"\\windows\somenetwork\somedrive"
LOG1 = open(LOGDIR+'\myStdOut.txt', 'w')
LOG2 = open(LOGDIR+'\myStdErr.txt', 'w')

class MyTest(unittest.TestCase):

currentResult = None # holds last result object passed to run method

def setUp(self):
    pass

def tearDown(self):
    ok = self.currentResult.wasSuccessful()
    errors = self.currentResult.errors
    failures = self.currentResult.failures
    print ' All tests passed so far!' if ok else \
            ' %d errors and %d failures so far' % \
            (len(errors), len(failures))

def run(self, result=None):
    self.currentResult = result # remember result for use in tearDown
    unittest.TestCase.run(self, result) # call superclass run method

def test_onePlusOneEqualsTwo(self):
    self.assertTrue(1 + 1 == 2) # succeeds

def test_onePlusOneEqualsThree(self):
    self.assertTrue(1 + 1 == 3) # fails

def test_onePlusNoneIsNone(self):
    self.assertTrue(1 + None is None) # raises TypeError

if __name__ == '__main__':
    sys.stdout = LOG1 
    sys.stderr = LOG2
    unittest.main()
    LOG1.close()
    LOG2.close()

在Linux上运行相同的脚本或至少写入文件:

import sys
import unittest

LOGDIR = r"/tmp"
LOG1 = open(LOGDIR+'/myStdOut.txt', 'w')
LOG2 = open(LOGDIR+'/myStdErr.txt', 'w')

class MyTestLinux(unittest.TestCase):

currentResult = None # holds last result object passed to run method

def setUp(self):
    pass

def tearDown(self):
    ok = self.currentResult.wasSuccessful()
    errors = self.currentResult.errors
    failures = self.currentResult.failures
    print ' All tests passed so far!' if ok else \
            ' %d errors and %d failures so far' % \
            (len(errors), len(failures))

def run(self, result=None):
    self.currentResult = result # remember result for use in tearDown
    unittest.TestCase.run(self, result) # call superclass run method

def test_onePlusOneEqualsTwo(self):
    self.assertTrue(1 + 1 == 2) # succeeds

def test_onePlusOneEqualsThree(self):
    self.assertTrue(1 + 1 == 3) # fails

def test_onePlusNoneIsNone(self):
    self.assertTrue(1 + None is None) # raises TypeError

if __name__ == '__main__':
    sys.stdout = LOG1 
    sys.stderr = LOG2
    unittest.main()
    LOG1.close()
    LOG2.close()

2 个答案:

答案 0 :(得分:2)

Windows上有can't reassign sys.stdout to redirect output when a script is started via a Windows file association的问题。您可以尝试修复它的Windows hotfix。或者您应该能够明确地调用python yourscript.py来解决它。

答案 1 :(得分:1)

这可能不是最好的方法,但它有效(at least on my machine):

import os
import sys
import unittest

STDOUT_FD = os.dup(sys.stdout.fileno())
STDERR_FD = os.dup(sys.stderr.fileno())

with open('stdout.txt', 'w') as f, open('stderr.txt', 'w') as g:
    os.dup2(f.fileno(), sys.stdout.fileno())
    os.dup2(g.fileno(), sys.stderr.fileno())


class MyTest(unittest.TestCase):
    def test_print(self):
        print 'some output'
        self.assertEqual('', '')

    def test_some_moar(self):
        print 'some other cool output'
        self.assertTrue(True)

if __name__ == '__main__':
    unittest.main()

print 'I am printing to stdout.txt'
print >> sys.stderr, 'I am printing to stderr.txt'

# revert the File Descriptors
os.dup2(STDOUT_FD, sys.stdout.fileno())
os.dup2(STDERR_FD, sys.stderr.fileno())

print "Yay! Back to printing in the console"

运行它会产生:

stdout.txt

some output
some other cool output

的stderr.txt

..
----------------------------------------------------------------------
Ran 2 tests in 0.000s

OK

os.dup(FD)

os.dup函数创建文件描述符的副本,并返回该重复文件描述符的整数。因此,在前两个dup调用之后,有两个文件描述符指向stdout,两个指向stderr

os.dup2(fd,fd2)

os.dup2函数将文件描述符从fd复制到fd2并关闭fd2的文件描述符。因此,在dup2调用之后,stdout现在指向f文件描述符,同样stderr现在指向g文件描述符(并且因为{{ 1}}关闭第二个文件描述符,dup2stdout只有一个文件描述符,因为调用stderr所产生的副本。

打印一切内容。

最后,最后两个dup调用使用复制的文件描述符恢复文件描述符(因此stdout和stderr指向您期望的位置),这也会关闭文件dup2和{{ 1}}。

根据dup2文档,这适用于Linux和Windows。

[编辑]

如果不是太多工作,我建议不要使用打印件而是使用f代替:

g
相关问题