Я написал пакет python, который мне удалось сделать полностью совместимым как с python 2.7, так и с python 3.4, за одним исключением, которое меня пока ставит в тупик. Пакет включает сценарий командной строки, и в своих модульных тестах я использую этот код для запуска основной процедуры сценария, переопределяя sys.argv для передачи аргументов командной строки для argparse и захвата stdout сценария для сравнения:
@contextlib.contextmanager
def runmain(mainfunction, arglist):
"""Run mainfunction with arglist in sys.srgv, and capture stdout."""
origargv, sys.argv = sys.argv, arglist
origout, sys.stdout = sys.stdout, io.StringIO()
rtn = mainfunction()
sys.stdout.seek(0)
yield (rtn, sys.stdout.read())
sys.stdout = origout
sys.argv = origargv
class test_imdutil_main(unittest.TestCase):
def test_help(self):
"""Test -h option."""
with runmain(imdutil_main, ['imdutil.py', '-h']) as (rtn, capture):
# do stuff with rtn and capture...
Это хорошо работает в python 3.4, но в python 2.7 генерирует ошибку:
TypeError: unicode argument expected, got 'str'
Мне не удалось найти способ захвата stdout из произвольных функций, который переносится между python 2.7 и python 3.4.
В стороне, я должен признать, что я вообще не очень хорошо разбираюсь в декорациях, менеджерах контекста или ключевом слове yield. Вдохновение для моей функции runmain () пришло из:
http://schinckel.net/2013/04/15/capture-and-test-sys.stdout-sys.stderr-in-unittest.testcase/
Кстати, мой полный пакет, откуда взялся этот код, находится здесь:
https://github.com/NF6X/pyImageDisk
На данный момент его модульные тесты частично не работают в python 2.7 из-за этой проблемы. Может ли кто-нибудь помочь мне выяснить, как решить эту проблему перенаправления stdout портативным питоническим способом, желательно без добавления каких-либо внешних зависимостей?