python-3.x PEP 8-导入不在文件顶部,带有sys.path

cngwdvgl  于 2023-05-30  发布在  Python
关注(0)|答案(9)|浏览(174)

问题

PEP8有一个关于将导入放在文件顶部的规则:
导入总是放在文件的顶部,就在任何模块注解和文档字符串之后,模块全局变量和常量之前。
但是,在某些情况下,我可能想做一些类似的事情:

import sys
sys.path.insert("..", 0)

import my_module

在这种情况下,pep8命令行实用程序标记我的代码:
E402模块级导入不在文件顶部
通过sys.path修改实现PEP8合规性的最佳方法是什么?
为什么
我有这段代码是因为我遵循了Python搭车指南中给出的the project structure
该指南建议我有一个my_module文件夹,与tests文件夹分开,两者都在同一个目录中。如果我想从tests访问my_module,我想我需要将..添加到sys.path

zysjyyx4

zysjyyx41#

如果只有几个导入,您可以忽略那些import行上的PEP8:

import sys
sys.path.insert("..", 0)
import my_module  # noqa: E402
hwazgwia

hwazgwia2#

通常我在项目的子目录foo/tests中有多个包含测试的文件,而我正在测试的模块在foo/src中。为了从foo/tests运行测试而不出现导入错误,我创建了一个文件foo/tests/pathmagic.py,如下所示:

"""Path hack to make tests work."""

import os
import sys

bp = os.path.dirname(os.path.realpath('.')).split(os.sep)
modpath = os.sep.join(bp + ['src'])
sys.path.insert(0, modpath)

在每个测试文件中,我使用

import pathmagic  # noqa

作为第一个进口。“noqa”注解防止pycodestyle/pep8抱怨未使用的导入。

dba5bblo

dba5bblo3#

还有另一个解决方法。

import sys
... all your other imports...

sys.path.insert("..", 0)
try:
    import my_module
except:
    raise
qltillow

qltillow4#

这个问题已经有几个解决方案,但是如果你有很多非初始导入,并且不想用# noqa: E402注解每个导入(或者使用其他建议之一),下面的方法适用于整个块:

import sys
sys.path.insert("..", 0)

if True:  # noqa: E402
    import my_module_1
    import my_module_2
    ...
5ktev3wc

5ktev3wc5#

我刚刚也在纠结一个类似的问题,我想我找到了一个比公认的答案稍微好一点的解决方案。
创建一个pathmagic模块来执行实际的sys.path操作,但在上下文管理器中进行更改:

"""Path hack to make tests work."""

import os
import sys

class context:
    def __enter__(self):
        bp = os.path.dirname(os.path.realpath('.')).split(os.sep)
        modpath = os.sep.join(bp + ['src'])
        sys.path.insert(0, modpath)

    def __exit__(self, *args):
        pass

然后,在您的测试文件中(或任何您需要的地方),您可以:

import pathmagic

with pathmagic.context():
    import my_module
    # ...

这样你就不会从flake 8/pycodestyle那里得到任何抱怨,你不需要特别的注解,而且结构看起来很有意义。
为了更加整洁,考虑实际还原__exit__块中的路径,尽管这可能会导致延迟导入的问题(如果您将模块代码放在上下文之外),因此可能不值得麻烦。

EDIT:刚刚看到一个answer to a different question中的一个简单得多的技巧:在导入下添加assert pathmagic以避免noqa注解。

6ioyuze2

6ioyuze26#

您是否已尝试以下操作:

import sys
from importlib import import_module

sys.path.insert("..", 0)

# import module
my_mod = import_module('my_module')

# get method or function from my_mod
my_method = getattr(my_mod , 'my_method')
bnl4lu3b

bnl4lu3b7#

为了符合pep 8,你应该在python路径中包含你的项目路径,以便执行相对/绝对导入。
要做到这一点,你可以看看这个答案:Permanently add a directory to PYTHONPATH

ojsjcaue

ojsjcaue8#

假设要添加的路径是相对于脚本的,这可以通过使用相对路径来解决。

from ..mypath import mymodule 
from ..mypath.mysubfolder import anothermodule

然后不再需要使用sys.path.insert()。林特停止了抱怨。

xmd2e60i

xmd2e60i9#

最简单的解决方案:在pytest的情况下,将在conftest.py中添加路径。这可确保在运行任何测试之前添加包路径。

相关问题