从不是子文件夹的另一个文件夹导入python文件

时间:2019-12-02 21:46:23

标签: python python-3.x python-import

我想要的

所以我正在使用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

一个简短的解释:

  • 我在每个“任务”文件中使用相同的功能
  • 我没有在每个“任务”文件中放置函数,而是在函数存在的地方创建了一个帮助文件
  • 我想将帮助文件“ ReadHelper.py”导入到我的任务文件中

我尝试过的

例如在文件task11.py中:

  • from Helpers.FileHelper.ReadHelper import *
  • import os, sys
    parentPath = os.path.abspath("../../")
    if parentPath not in sys.path:
        sys.path.insert(0, parentPath)
    from Helpers.FileHelper.ReadHelper import *
    
  • import os, sys
    sys.path.append('../../')
    from Helpers.FileHelper.ReadHelper import *
    

以上解决方案均无效,因为我总是会遇到以下错误: ModuleNotFoundError: No module named 'Helpers'

我也尝试过:

  • from ..Helpers.FileHelper.ReadHelper import *

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

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


P.S

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


更新1

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

一个缺点是该交互式窗口启动缓慢,无法处理输入。

我也尝试了@Omni的答案:

$> python -m root.dir1.task11

它奏效了!但是正如他所说的那样,它存在一个缺点,那就是输入终端的速度很慢。

因此,我尝试在Visual Studio Code中创建一个任务,该任务可以为我当前所在的文件执行上述shell命令,但未成功。

您知道如何在vscode中创建任务以运行上述命令吗?


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


更新2

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

基本上我所做的是:

  • 创建了一个pyhton脚本
  • 使用Visual Studio代码创建任务

现在,我只需按cmd + shift + B就可以运行带有导入的python文件。


说明

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文件,并通过参数传递活动文件的路径

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()
  • 此python脚本获取活动文件的路径作为参数
  • 然后它会创建路径的shell命令(shell命令就像@kasper-keinänen的答案一样)
  • 然后运行该shell命令

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

我只需要按cmd + shift + B就可以做到。

5 个答案:

答案 0 :(得分:2)

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

如果您运行task11.py脚本,则:

$ python3 -m dir1.task11 

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

from Helpers.FileHelper.ReadHelper import *

答案 1 :(得分:1)

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

答案 2 :(得分:1)

如果您只是想在 VSCode 中执行此操作,而不是在正常运行时执行此操作。您可以在 .vscode/settings.json

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

enter image description here

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

答案 3 :(得分:0)

将完整的绝对路径添加到sys.path变量将使其起作用。

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

from ReadHelper import *

答案 4 :(得分:0)

问题在于您的文件/文件夹结构。我建议您在根文件夹中创建一种“控制”文件,然后可以从上至下使用它来引用所有其他模块。

因此,假设您的根文件夹中有一个名为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 *-假设您不打算使用此文件夹在您自己的机器以外的其他机器上。