从父目录导入Python并保持flake8愉快

时间:2017-03-16 04:08:14

标签: python python-import flake8

此导入工作正常,但在某些方面感觉很脏。主要是它使用切片*中的特定数字来获取父路径,并且它会使flake8 linter烦恼。

import os
import sys
sys.path.append(os.path.dirname(__file__)[:-5])
from codeHelpers import completion_message

它位于文件系统中,看起来有点像这样:

parent_folder
    __init__.py
    codeHelpers.py

    child_folder
        this_file.py

child_folder实际上称为week1,因此切片中为5

这个问题与Python import from parent directory极为相似,但在这种情况下,讨论的重点是从终点运行测试是否合适。 In my case,我有一系列目录,其代码使用父级中的帮助程序。

上下文:每个目录都是一组每周练习,所以我希望尽可能简单。

是否有更清洁,更pythonic的方式来进行此导入?

@cco解决了数字问题,但它仍然让烦恼感到不安。

5 个答案:

答案 0 :(得分:3)

首先,因为你没有具体说明你得到的lint错误,我将假设这是因为你在sys.path.append之后有一个导入。

最干净的方法是使用相对或绝对进口。

使用绝对导入:

from parent_path.codeHelpers import completion_message

使用相对导入:

from ..codeHelpers import completion_message

对于原始问题中列出的简单示例,这应该是所有必需的。它很简单,它是pythonic,它是可靠的,它修复了棉绒问题。

您可能会发现上述情况对您不起作用,仍然需要进行sys.path操作。缺点是您的IDE可能无法从新路径解析对模块的导入,从而导致自动代码完成无效等问题,并将导入标记为错误,即使代码运行正常。

如果您发现仍需要使用sys.path并希望避免此类情况的lint错误,请创建一个新模块并在其中执行sys.path操作。然后确保在任何需要修改sys.path

的模块之前导入新模块

例如:

local_imports.py

"""Add a path to sys.path for imports."""

import os
import sys

# Get the current directory
current_path = os.path.dirname(__file__)

# Get the parent directory
parent_path = os.path.dirname(current_path)

# Add the parent directory to sys.path
sys.path.append(parent_path)

然后在目标文件中:

import local_imports  # now using modified sys.path
from codeHelpers import completion_message

缺点是它要求您在每个local_imports.py中包含child_folder,如果文件夹结构发生变化,则必须修改每个local_imports文件。

这种模式真正有用的地方是你需要在包中包含外部库(例如在libs文件夹中)而不需要用户自己安装库。

如果您将此模式用于libs文件夹,则可能需要确保所包含的库优先于已安装的库。

为此,请更改

sys.path.append(custom_path)

sys.path.insert(1, custom_path)

这将使你的自定义路径成为python解释器检查的第二位(第一个仍然是'',这是本地目录。)

答案 1 :(得分:2)

您可以使用..从模块中导出级别的模块。在this_file.py中:

from ..codeHelpers import completion_message

如果你想要更多关卡,只需继续添加点......

虽然我在这里,但请注意from ..codeHelpers相对导入,并且在导入同一个包中的内容时应始终使用它们。 from codeHelpers是一个绝对导入,在Python 2中是不明确的(它应该从包中导入还是从您系统上安装的不幸名为codeHelpers的模块中导入?)实际上禁止在Python 3中作为从同一模块中导入的方式(即它们总是绝对的)。你可以阅读古代PEP 328来解释困难。

答案 2 :(得分:2)

使用绝对导入路径可能更容易,如下所示:

from parent_folder.code_helpers import completion_message

但这需要您确保设置PYTHONPATH环境变量,以便它可以看到最高的根目录(在这种情况下为parent_folder,我认为)。例如,

PYTHONPATH=. python parent_directory/child_directory/this_file.py
# here the '.' current directory would contain parent_directory

确保同时向child_directory添加__init__.py

答案 3 :(得分:1)

您可以通过两次应用os.path.dirname来删除有关最终目录名称长度的假设。

e.g。而不是os.path.dirname(__file__)[:-5],请使用os.path.dirname(os.path.dirname(__file__))

答案 4 :(得分:1)

无论哪种方式,你都要乱搞。如果你的主要目标是避免剥落警告

  • 添加noqa评论
  • exec(open("../codeHelpers.py").read(), globals())

  • 你可以传递一个带解释器选项-c的文件名(不应该打扰flakes8)