5

此导入工作正常,但在某些方面感觉很脏。主要是它使用 slice* 中的特定数字来获取父路径,并且它会惹恼 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非常相似,但在这种情况下,讨论的重点是从终点运行测试是否好。就我而言,我有一系列目录,其中包含使用父级中的帮助程序的代码。

背景:每个目录都是一组每周练习,所以我想让它们尽可能简单。

有没有一种更简洁、更 Pythonic 的方式来执行此导入?

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

4

5 回答 5

4

首先,由于您没有具体说明您遇到了哪个 lint 错误,我假设这是因为您在sys.path.append.

最干净的方法是使用相对或绝对导入。

使用绝对导入:

from parent_path.codeHelpers import completion_message

使用相对导入:

from ..codeHelpers import completion_message

对于原始问题中列出的简单示例,这应该是所需要的。它很简单,它是 pythonic,它是可靠的,并且它修复了 lint 问题。

您可能会发现自己处于上述情况对您不起作用并且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 解释器检查的第二个位置(第一个仍然''是本地目录)。

于 2017-04-08T12:15:24.093 回答
2

您可以使用 . 从模块导入包中的更高级别..。在 this_file.py 中:

from ..codeHelpers import completion_message

如果您想升级更多级别,请继续添加点...

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

于 2017-04-03T16:17:02.027 回答
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

确保也将一个添加__init__.py到 child_directory。

于 2017-04-06T00:04:29.037 回答
1

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

例如,代替os.path.dirname(__file__)[:-5],使用os.path.dirname(os.path.dirname(__file__))

于 2017-03-16T04:19:04.283 回答
1

无论哪种方式,你都必须破解。如果您的主要目标是避免片状警告

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

  • 您可以使用解释器选项 -c 传递文件名(不应该打扰 flakes8)

于 2017-04-07T19:26:50.740 回答