如何将Python模块添加到sys.path?

我有一个像这样的文件结构:
Folder
   Common
      foo1.py
   TestFolder
      foo2.py

我想导入 foo2.pyfoo1.py。我尝试过了,但在 Ubuntu 上不起作用。

sys.path.append(os.path.abspath('../../'))
from Common import foo1.py

你的文件夹里有一个 __init__.py 文件吗?这是Python创建包并允许你从该包中导入模块的方式。http://guide.python-distribute.org/creation.html - Bryan
我在 Common 文件夹和 TestFolder 文件夹中有一个 init.py 文件。 - user284474
如果你想要导入,你需要将它放在文件夹目录以及子文件夹中。 - Bryan
1这个 init.py 是空的吗? - user284474
2是的,它可以为空。除非您需要特定配置来处理您的包裹,但如果它为空,您应该没问题。 - Bryan
@Bryan 我觉得你说得对,我已经把它作为一个答案添加了。随时可以自己添加答案,我会删除我的答案。下次可以直接发布为答案。 - don.joey
3个回答

Python如何找到它的模块

严格来说,一个模块是一个单独的Python文件,而一个是一个包含Python文件的文件夹,还有一个(可以为空)名为__init__.py的文件,告诉Python这是一个可以从中导入模块的包。在这两种情况下,模块需要有.py扩展名,但导入它们时不需要扩展名(请参见下文)。

默认情况下,Python在$PYTHONPATH中查找它的模块和包。

要查看$PYTHONPATH中包含了哪些内容,请在Python(3)中运行以下代码:

import sys
print(sys.path)

如何添加目录
偶尔
在Python文件中,您可以通过在Python应用程序或脚本的头部部分添加以下行来偶尔将路径添加到默认路径中:
import sys
sys.path.insert(0, "/path/to/your/package_or_module")

例如:
如果我有一个文件夹:/home/myname/pythonfiles,并且我想要导入位于该目录中的文件module_1.py,我将以下内容添加到我的代码头部部分:
import sys
sys.path.insert(0, "/home/myname/pythonfiles")

我可以通过以下方式简单地导入文件module_1.py
import module_1

当我创建一个并且想要从包中导入模块时,我需要在$PYTHONPATH中创建一个文件夹,其中包含模块,并附上一个(可以是空的)名为__init__.py的文件。 例如: 要从名为my_package的包(文件夹)中在/home/myname/pythonfiles中导入,将/home/myname/pythonfiles路径添加到$PYTHONPATH中,就像示例1那样,并通过以下方式简单地导入包文件夹内的module_2.py模块:
`
from <packagename> import module_2

将目录永久添加到$ PYTHONPATH:
将以下行添加到您的~ / .profile文件中。
export PYTHONPATH=$PYTHONPATH:/path/you/want/to/add

子目录

在包内部,子目录不会自动包含;您需要“链接”这些目录。要导入文件夹packagenamesubfolder文件夹内的模块module_3.py

import packagename.subfolder.module_3

鉴于包中的所有子文件夹都包含自己的__init__.py文件。
当一个模块与脚本或应用程序位于同一目录中时,
无需插入模块的路径,因为它会自动添加。
例如:
如果我有一个包含script.pymodule.py的文件夹,我可以通过以下方式简单地导入该模块:
import module

1我还想建议阅读https://www.python.org/dev/peps/pep-0328/,特别是如果你的目标是Python 3(或计划将来的目标)。 - zaadeh
1为什么 printenv PYTHONPATH 没有任何输出? - tread
2sys.path.append("/path/to/your/package_or_module") 这个也可以把路径添加到默认路径里面,而且不会那么容易搞混。相比之下,sys.path.insert(0,...)0 作为第一个参数。 - Paul Rougieux
3@PaulRougieux:追加路径的问题在于,你的模块可能已经存在于路径的其他位置(例如在一个.egg文件中),这样你就会选择那个版本的模块,而不是你文件中的那个版本。 - snark

正确使用相对导入的方法是:
from ..Common import foo1

而且你还需要在所有的文件夹中添加一个__init__.py文件。

1谢谢。但是如果我有一个模块在两个文件夹之上,那么如何导入呢?使用“....文件夹”是不起作用的。 - user284474
能在单层使用吗? - Sylvain Pineau
只有一个级别,它就能正常工作。 - user284474
好的,你能接受这个答案吗?对于多级别的问题,你可以提出一个不同的问题,但首先看一下这个问题和这个答案,以了解在包内调用模块的最佳方式。 - Sylvain Pineau
这对Python 2还是Python 3适用吗?还是两者都适用? - alex
我会避免使用相对导入,因为有太多的方式让它出错。除非你的文件结构是扁平的,并且你知道它将保持不变,否则这种方式充满了陷阱。只需搜索一下关于相对导入问题的困扰,就能看到有多少种方式。 - neuronet
重要更新:在Python 3中,包含模块的目录将被自动视为一个包,无需__init__.py文件。 - Luk Aron

NB: 这个答案已经过时,适用于早期版本的Python 3。但是为了更多信息,请阅读评论和https://www.python.org/dev/peps/pep-0420/
基本上,你想要添加到syspath的每个带有Python代码的文件夹都需要一个__init__.py文件。这些__init__.py文件可以是空的。

据我所了解,这已不再是事实,目录现在变成了一个“命名空间”。 - Aaron Hall
@AaronHall 有趣,来源是什么? - don.joey
1试试这个作为证据:python -c "from pathlib import Path; Path('ns').mkdir(); Path('ns/mod.py').write_text('''print('mod.py')'''); import ns.mod; from shutil import rmtree; rmtree('ns')" 这里还有一些相关的文档,PEP 420,描述了命名空间包语义的添加 - Aaron Hall

  • 相关问题