Python 2 下的 运行 脚本如何忽略 Python 3 语法?

How can I ignore Python 3 syntax when running script under Python 2?

当 运行ning 脚本在 Python 2 下时,是否可以忽略或屏蔽掉 Python 3 语法片段?

我正在尝试针对 Python 2 或 Python 3 下的 Python 模块针对 运行 编写单元测试。

该测试包含仅在 Python 3 ("yield from") 下有效的语法 - 我只想 运行 在 运行 时进行这些测试Python 3 上的测试。当我在 Python 2 下 运行 时,是否有一种方法可以禁用或屏蔽此 Python 3 代码,这样我就不会得到当我 运行 unittest 模块时抛出语法错误?

请参阅下面的缩减示例:

import unittest
try:
    import asyncio
    # We must be running under Python 3 - run the sync and async tests.
    ASYNC_SUPPORTED = True
except ImportError:
    # We must be running under Python 2 - only run the sync tests.
    ASYNC_SUPPORTED = False

class TestSyncMethods(unittest.TestCase):
    def test_1(self):
        # Test for synchronous functionality here
        pass

# Test for asynchronous functionality here
class TestAsyncMethods(unittest.TestCase):
    @unittest.skipIf(not ASYNC_SUPPORTED, "Async not supported")
    def test_async_1(self):
        @asyncio.coroutine
        def go():
            yield from sc.identify_a(1, 0x2B, True, True)

如果我尝试 运行 在 Python 2.x 下进行此单元测试,我会在 "yield from" 指令处遇到语法错误,因为 "yield from" 不受支持在 Python 2.x 下。理想情况下,如果单元测试在 Python 2.x 下 运行,我想阻止整个 TestAsyncMethods class 被解析。有谁知道有什么办法吗?

这个怎么样:

from sys import version_info

if version_info[0] > 2:
    ASYNC_SUPPORTED = True
    import asyncio
else:
    ASYNC_SUPPORTED = True
    asyncio = None

正如 Alexander 指出的那样,您仍然需要拆分 py2 和 py3 模块。除非你打算通过 exec 发挥创意,我强烈建议你不惜一切代价避免这种情况。

实现此目的的一个好方法是根据名称排除模块,以避免尝试导入它们。

这是我目前使用的约定:所有 python2 和 python3 兼容的测试都有一个“_py2_py3”后缀,所有仅 [=28] 的模块=] 兼容有一个“_py3”后缀,所有仅 python2 兼容的模块有一个“_py2”后缀等等。

至运行 所有测试:

python -m unittest discover -s project_directory -p "test*.py"

运行 python2 测试:

python -m unittest discover -s project_directory -p "test*_py2*.py"

运行 python3 测试:

python -m unittest discover -s project_directory -p "test*_py3*.py"

如果需要,您可以创建一个测试 运行ner:

# test_runner.py

import unittest

import six

if six.PY2:
    PATTERN = 'test*_py2*.py'
else:
    PATTERN = 'test*_py3*.py'


def start():
    unittest.main(
        module=None,
        argv=[
            'my_app', 'discover',
            '-s', 'tests',
            '-p', PATTERN])


if __name__ == '__main__':
    start()