0

我有以下目录结构:

base_folder
    methods_folder
        method_1.py
        method_2.py
        .
        .
        .
        method_n.py
        class_methods.py
    top_class.py
    

class_methods.py导入同一目录中的其他文件,如下所示:

from method_1 import method_1
from method_2 import method_2
.
.
.
from method_n import method_n

(obs:这些methods文件有一个方法,里面有自己的文件名)

如果我class_methods.py自己跑,没问题。但是,如果我尝试运行top_class.py导入class_methods.py,则会收到错误消息no module named method_1

因此,在执行时top_class.py,它看不到methods_folder/. 为什么?

4

5 回答 5

0

运行 python 脚本的推荐方法是使用-m根包父级的开关 - 所以在你的情况下:

$ cd base_folder
$ python -m top_class

Python 会自动将 base_folder 添加到它的 sys.path 中,你不需要做任何 sys.path/PYTHOPATH 黑客攻击——这些黑客攻击会用样板文件使代码膨胀,并且会在最意想不到的时候崩溃。

现在运行 class_methods 的正确方法也是

$ cd base_folder
$ python -m methods_folder.class_methods

但随后的导入class_methods应修改为绝对值:

from methods_folder.method1 import method1
...

或亲戚:

from .method1 import method1
...
于 2020-12-11T09:56:04.783 回答
0

里面的正确导入top_class.pyfrom methods_folder.method_n import method_n. 这是因为您将methods_folder其视为一个包。如果您运行的是 3.3 之前的 Python 版本,您还必须__init__.py在其中取消包含文件methods_folder才能将其转换为包。

于 2020-12-09T23:53:07.773 回答
0

我假设您是从它们各自的目录运行它们?除非它们安装在您的 Python 路径中(我假设它们没有安装),否则 Python 默认会在您的当前目录中查找导入。因此,当您从其目录运行 class_methods.py 时,它可以找到 methods_1.py 以满足from methods_1 import method_1. 但是,当您执行 top_class.py 时,它会查找methods_1.pyor methods_1/__init__.py,这两个都不会从该目录中罚款。

假设 Python 3,您需要在class_methods.py.

# class_methods.py
from .methods_1 import method_1
from .methods_2 import method_2

这将让您从top_class.py. 不幸的是,在同一个包中运行脚本时,您不能使用相对导入,因此您将无法class_methods.py直接运行。

在这种情况下,另一个选择是保留绝对导入class_methods.py并将方法文件夹添加到top_class.py.

import os 
import sys

sys.path.append(os.path.join(os.path.dirname(__file__), 'methods'))

import class_methods
from methods_1 import method

当然,编辑 sys.path 对于小脚本和独立的东西是很好的。但是,如果这不再是一个脚本,那么您需要小心执行它,并且您可能只想想出另一个解决方案。可能,最好的办法是创建一个您安装的包(您仍然可以在开发时从源目录执行此操作),然后您可以从任何地方以相同的方式导入。

于 2020-12-09T23:54:38.033 回答
0

文件只能直接访问它们导入的内容。假设我们有a.pywhich importsb.pyb.pyimports c.py。在该 use的a.py函数中运行时,这将正常工作,因为可以访问,并且可以访问. 然而,这并不意味着导入链(如在 C++ 中)和您可以使用in 中的函数。你会得到一个错误,因为只能看到它导入的内容。b.pyc.pyabbccaab

因此,如果您想使用其中的所有method_i.py文件top_class.py,则需要将它们直接导入同一个文件中。

编辑:您还有其他一些问题。要在子文件夹中导入其他文件,您需要在内部top_class.py调用import methods_folder.method_i. 要在同一目录中导入某些内容,只需使用import method_i. 由于您在每个文件中都有一个同名的方法,因此您可以在其中正常工作class_methods.py您还需要创建一个空文件__init__.py,该文件在包含您打算导入/从中导入的 python 文件的任何文件夹中调用,让 python 知道它可以在那里查看.

于 2020-12-09T23:54:47.260 回答
0

您可以通过以下两种方式之一在 python 中创建可导入包。第一种方法是您正在做的事情:您创建一个名为的文件my_package.py并使用import my_package. 这通常用于不需要进一步分解的更简单的包。为此,您的 .py 文件必须位于PYTHONPATH它是一个环境变量,它告诉 python 在哪里查找包。如果未定义,python 将使用一些默认位置来查找包。其中一个默认位置是当前工作目录,这就是您的第一组导入工作的原因。

理论上,您应该能够从同一位置 ( ) 运行第二段代码python ../top_class.py并使用相同的导入样式,但我假设您正在更改目录以运行该文件。这意味着您的文件不再位于当前工作目录中,并且不再被 python 找到。

使用现有样式让代码工作的一种方法是使用PYTHONPATHmethodX.py 文件的位置进行定义。您通常会像这样添加到 python 搜索路径:

PYTHONPATH=$PYTHONPATH:./methods_folder python top_class.py

methods_folder当您尝试导入某些内容时,这会告诉 python 在标准位置之外查找。玩PYTHONPATH一段时间后会有点烦人,所以我实际上更喜欢下一种方法。

创建包的第二种方法是创建一个包含文件的__init__.py文件夹。这告诉 python 你希望它将该目录视为一个包。对于可能受益于跨多个文件的组织的更复杂的代码片段,这是首选样式。对于您的示例,您可以按以下方式组织代码:

base_folder
    methods_folder
        __init__.py
        method_1.py
        method_2.py
        .
        .
        .
        method_n.py
        class_methods.py
    top_class.py

然后您的导入top_class.py将如下所示:

from methods_folder.method1 import method1
from methods_folder.method2 import method2
from methods_folder.method3 import method3

methods_folder这具有创建带有 modules method1method2等的顶级包的效果。因为methods_folder与您正在运行的目录位于同一目录中top_class.py,python 使用默认值将其作为包选择PYTHONPATH并允许您从其中导入。

于 2020-12-09T23:58:26.783 回答