从另一个非子文件夹导入 python 文件

Import python file from another folder that is not a child

我想要的

我正在使用 Visual Studio 代码和 Python 3.7.0,我只是想从另一个文件夹导入另一个 Python 文件到我的 python 文件.


详情

这是我的文件夹结构

root/
    dir1/
        data.txt
        task11.py
        task12.py
    dir2/
        data.txt
        task21.py
        task22.py
    Helpers/
        FileHelper/
            ReadHelper.py

所以简短的解释:


我试过的

例如在文件中 task11.py:

None 上述解决方案有效,因为我总是以错误告终: ModuleNotFoundError: No module named 'Helpers'

我也试过:

但最终出现错误:ValueError: attempted relative import beyond top-level package

那么如何将文件 ReadHelper.py 导入我的任务文件?


P.S

有一些类似的问题,但它们真的很老,答案对我没有帮助。


更新 1

Visual Studio 代码中有一个选项,如果我 运行 使用此导入 from Helpers.FileHelper import ReadHelper 此命令,则不会生成错误并且代码可以完美执行。

一个缺点是此交互式 window 启动速度慢,无法处理输入。

我也试过@Omni的回答:

$> python -m root.dir1.task11

它奏效了!但正如他所说,有一个缺点:在终端中输入速度很慢。

所以我尝试在 Visual Studio 代码中创建一个任务,可以对我当前所在的文件执行上述 shell 命令,但没有成功。

你知道如何在vscode到运行上面的命令中创建任务吗?


我还尝试在每个目录下添加 __init__.py 文件,这样它们就会被视为包 Python3 tutorial - 6.4 Module Packages。但这并没有帮助,并且发生了同样的错误。


更新 2

我想出了一种方法,使拥有这样的文件夹结构变得非常容易,并使导入在终端中正常工作。

基本上我所做的是:

有了这个,我现在可以 运行 我的 python 文件,只需按 cmd + shift + B


说明

visual studio任务:

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "Run python file",
            "type": "shell",
            "command": "python3 /PATH_TO_ROOT_FOLDER/run_python_file.py ${file}",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "presentation": {
                "reveal": "always",
                "panel": "new",
                "focus": true
            }
        }
    ]
}

我们要重点关注的部分是:

"command": "python3 /PATH_TO_ROOT_FOLDER/run_python_file.py ${file}",

python脚本:

import os, sys

# This is a argument given trough a shell command
PATH_TO_MODULE_TO_RUN = sys.argv[1]

ROOT_FOLDER = "root/"

def run_module_gotten_from_shell():
    # Here I take only the part of the path that is needed
    relative_path_to_file = PATH_TO_MODULE_TO_RUN.split(ROOT_FOLDER)[1]
    
    # Creating the shell command I want to run
    shell_command = createShellCommand(relative_path_to_file)

    os.system(shell_command)


# Returning "python3 -m PATH.TO.MODULE"
def createShellCommand(relative_path_to_file):
    part1 = "python3"
    part2 = "-m"

    # Here I change the string "dir1/task11.py" => "dir1.task11"
    part3 = relative_path_to_file.replace("/", ".")[:-3]

    shell_command = "{:s} {:s} {:s}".format(part1, part2, part3)
    return shell_command

run_module_gotten_from_shell()

通过这些修改,我可以 运行 根目录中的任何文件,并从根目录中的任何文件导入。

而且我只需按 cmd + shift + B 即可。

将完整的绝对路径添加到 sys.path 变量应该可以正常工作。

import sys
sys.path.append('/full/path/to/Helpers/FilesHelper/')

from ReadHelper import *

a) 在了解辅助函数的环境中将任务模块作为脚本执行。这样,taks 模块中的代码就不必知道任何关于包结构的信息。它模仿 python 解释器的内置函数。

   # cli argument #1 is the task module to execute
   import sys  
   task_to_execute = sys.argv[1]

   from Helpers.FileHelper.ReadHelper import *
   exec(open(task_to_execute).read())

b) 正确使用相对导入。为此,您必须通过(这可能是此解决方案的缺点)执行任务代码。

   $> python -m root.dir1.task11.task11

问题出在您的 file/folder 结构上。我建议在您的根文件夹中创建一种 'control' 文件,然后可以自上而下地引用所有其他模块。

假设您的根文件夹中有一个名为 MasterTask.py 的文件,它可能如下所示:

from dir1.task11.task11 import *
from dir1.task12.task12 import *
from dir2.task21.task21 import *
from dir2.task22.task22 import *
from Helpers.FileHelper.ReadHelper import *

class Master:
#Do your task work here
    pass

另一种选择是将 Helpers 文件夹移动到您的 Python37\Lib\site-packages 文件夹中,这也允许按原样使用 from Helpers.FileHelper.ReadHelper import * - 假设您不打算使用它在您自己以外的其他机器上。

您可以尝试 运行 使用 -m 选项连接脚本,该选项允许使用 Python 模块命名空间 docs.python.org.

定位模块

如果您 运行 task11.py 脚本那么:

$ python3 -m dir1.task11 

然后在 task11.py 中执行如下导入:

from Helpers.FileHelper.ReadHelper import *

如果您只是想在 VSCode 内尝试这样做,而不是在正常的 运行 时间内。您可以在 .vscode/settings.json

中添加路径
{
    "python.analysis.extraPaths": [
        "${workspaceFolder}/webapp"
    ],
}

注意:这不能解决标准 Python 导入问题。我的用例特定于一个整体项目,其中所有编辑器配置文件都位于根目录中,因此我无法将 'webapp/' 作为工作区本身打开。