在Python2下运行脚本时,如何忽略Python3语法?

在Python2下运行脚本时,如何忽略Python3语法?,python,python-2.7,python-3.x,python-unittest,Python,Python 2.7,Python 3.x,Python Unittest,在Python2下运行脚本时,是否可以忽略或屏蔽Python3语法 我正在尝试编写一个单元测试,以针对Python2或Python3下的Python模块运行 测试包含的语法仅在Python3下有效(“yield from”)——我只想在Python3上运行测试时运行这些测试。当我在Python2下运行Python3代码时,是否有一种方法可以禁用或屏蔽该代码,以便在运行unittest模块时不会引发语法错误 请参见下面的简化示例: import unittest try: import a

在Python2下运行脚本时,是否可以忽略或屏蔽Python3语法

我正在尝试编写一个单元测试,以针对Python2或Python3下的Python模块运行

测试包含的语法仅在Python3下有效(“yield from”)——我只想在Python3上运行测试时运行这些测试。当我在Python2下运行Python3代码时,是否有一种方法可以禁用或屏蔽该代码,以便在运行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)
如果我试图在Python2.x下运行此unittest,我会在“yield from”指令中得到一个语法错误,因为Python2.x不支持“yield from”。理想情况下,如果unittest在Python2.x下运行,我希望防止对整个TestAsyncMethods类进行解析。有人知道怎么做吗?

这个怎么样:

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”后缀,所有仅与python3兼容的模块都有一个“_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"
如果需要,可以创建测试运行程序:

# 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()

您可以将它拆分为另一个文件,并有条件地导入它。理论上,如果没有语法错误,您可以使用six.PY3,或者其他类型的语法。但是,使用
\uuuuu future\uuuuuu
模块可以大大减少这样做的需要。@jonrsharpe条件导入应该是库配置的一部分,即它应该更改导入路径。谢谢大家。这听起来像是有条件的导入,但是,在本例中,我想知道这将如何影响nose之类的测试发现。我想我得吸一口看看。这并不能修复“yield from”语法,它会在Python2中产生一个SynaxError。整个文件本身无法导入,这就是为什么这里几乎需要执行条件导入。感谢您的帮助。如上所示的条件导入绝对是解决方案。不幸的是,我还没有找到一种方法来阻止单元测试发现工具(nose或py.test)在Python2下运行时查找和尝试解析/运行Python3模块(但这是另一个问题)。