python - 捕获标准输出时 python2 和 python3 之间的 StringIO 可移植性

标签 python python-2.7 stdout python-3.4 stringio

我已经编写了一个 python 包,我已经设法使它与 python 2.7 和 python 3.4 完全兼容,但有一个异常(exception)一直困扰着我。该软件包包含一个命令行脚本,在我的单元测试中,我使用此代码运行脚本的主例程,同时覆盖 sys.argv 以传递 argparse 的命令行参数,并捕获脚本的标准输出以进行比较:

@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'

我还没有找到一种方法来从可在 python 2.7 和 python 3.4 之间移植的任意函数中捕获 stdout。

顺便说一句,我不得不承认我根本不了解装饰、上下文管理器或“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 下被部分破坏。谁能帮我弄清楚如何以可移植的 pythonic 方式解决这个 stdout 重定向问题,最好不要再添加任何外部依赖项?

最佳答案

您将仅支持 Python 2 字节的 sys.stdout 替换为仅接受 Unicode 的。您必须在此处调整 Python 版本的策略,并使用不同的对象:

try:
    # Python 2
    from cStringIO import StringIO
except ImportError:
    # Python 3
    from io import StringIO

并删除上下文管理器中的 io. 前缀:

origout,  sys.stdout = sys.stdout, StringIO()

cStringIO.StringIO 对象在 Python 2 中等同于 io.BytesIO;它要求您编写纯字节串,而不是 unicode 对象。

您还可以在 Python 2 中使用 io.BytesIO,但您随后想要测试 sys.stdout 是否为 io.TextIOBase subclass ;如果不是,则将对象替换为二进制 BytesIO 对象,否则使用 StringIO 对象:

import io

if isinstance(sys.stdout, io.TextIOBase):
    # Python 3
    origout, sys.stdout = sys.stdout, io.StringIO()
else:
    # Python 2 or an unorthodox binary stdout setup
    origout, sys.stdout = sys.stdout, io.BytesIO()

关于python - 捕获标准输出时 python2 和 python3 之间的 StringIO 可移植性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34871605/

相关文章:

Python 3.2 中的 Python MD5 哈希比较

python2.7 : logging configuration with yaml

python-2.7 - 使用霍夫圆变换进行眼瞳跟踪

go - 从 `exec.Cmd` 中获取 "real-time"的输出

python re.split() : how to save some of the delimiters (instead of all the delimiter by using bracket)

python - manage.py runserver in virtualenv 使用错误的 django 版本

VSCode 似乎无法识别 Python3

python - 为什么 shell 输出会转到 stderr?

ruby - 如何编写一个程序来包装另一个程序的 STDOUT 和 STDIN?

python - AngularJS+Flask 无法实例化模块