Python 从父目录导入并让 flake8 满意

Ben*_*Ben 6 python python-import flake8

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

import os
import sys
sys.path.append(os.path.dirname(__file__)[:-5])
from codeHelpers import completion_message
Run Code Online (Sandbox Code Playgroud)

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

parent_folder
    __init__.py
    codeHelpers.py

    child_folder
        this_file.py
Run Code Online (Sandbox Code Playgroud)

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

这个问题与Python 从父目录导入非常相似,但在这种情况下,讨论的重点是从终点运行测试是否合适。就我而言,我有一系列目录,其中的代码使用位于父级中的帮助程序。

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

有没有一种更干净、更Pythonic的方法来执行此导入?

@cco 解决了数字问题,但它仍然扰乱了 linter。

小智 5

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

最简洁的方法是使用相对或绝对导入。

使用绝对导入:

from parent_path.codeHelpers import completion_message
Run Code Online (Sandbox Code Playgroud)

使用相对导入:

from ..codeHelpers import completion_message
Run Code Online (Sandbox Code Playgroud)

对于原始问题中列出的简单示例,这应该是所需的全部内容。它很简单,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)
Run Code Online (Sandbox Code Playgroud)

然后在目标文件中:

import local_imports  # now using modified sys.path
from codeHelpers import completion_message
Run Code Online (Sandbox Code Playgroud)

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

当您需要在包中包含外部库时(例如在libs夹中)包含外部库而不要求用户自己安装库时,此模式真正有用。

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

为此,请更改

sys.path.append(custom_path)
Run Code Online (Sandbox Code Playgroud)

sys.path.insert(1, custom_path)
Run Code Online (Sandbox Code Playgroud)

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