我正在尝试编写一个将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()
答案 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"
运行它会产生:
some output
some other cool output
..
----------------------------------------------------------------------
Ran 2 tests in 0.000s
OK
os.dup
函数创建文件描述符的副本,并返回该重复文件描述符的整数。因此,在前两个dup
调用之后,有两个文件描述符指向stdout
,两个指向stderr
。
os.dup2
函数将文件描述符从fd
复制到fd2
并关闭fd2
的文件描述符。因此,在dup2
调用之后,stdout
现在指向f
文件描述符,同样stderr
现在指向g
文件描述符(并且因为{{ 1}}关闭第二个文件描述符,dup2
和stdout
只有一个文件描述符,因为调用stderr
所产生的副本。
打印一切内容。
最后,最后两个dup
调用使用复制的文件描述符恢复文件描述符(因此stdout和stderr指向您期望的位置),这也会关闭文件dup2
和{{ 1}}。
根据dup2文档,这适用于Linux和Windows。
如果不是太多工作,我建议不要使用打印件而是使用f
代替:
g