如何导入给定相对路径的Python模块?
例如,如果dirFoo包含Foo.py和dirBar,而dirBar包含Bar.py,我如何将Bar.py导入Foo.py?
下面是一个视觉表示:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo希望包含Bar,但重组文件夹层次结构不是一个选项。
如何导入给定相对路径的Python模块?
例如,如果dirFoo包含Foo.py和dirBar,而dirBar包含Bar.py,我如何将Bar.py导入Foo.py?
下面是一个视觉表示:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo希望包含Bar,但重组文件夹层次结构不是一个选项。
当前回答
这同样有效,而且比使用sys模块简单得多:
with open("C:/yourpath/foobar.py") as f:
eval(f.read())
其他回答
如果您以这种方式构建项目:
src\
__init__.py
main.py
dirFoo\
__init__.py
Foo.py
dirBar\
__init__.py
Bar.py
然后,从Foo.py你应该能够做到:
import dirFoo.Foo
Or:
from dirFoo.Foo import FooObject
根据Tom的评论,这确实需要通过site_packages或搜索路径访问src文件夹。此外,正如他所提到的,__init__.py是在您第一次导入该包/目录中的模块时隐式导入的。通常__init__.py只是一个空文件。
添加__init__.py文件:
dirFoo\
Foo.py
dirBar\
__init__.py
Bar.py
然后将以下代码添加到Foo.py的开头:
import sys
sys.path.append('dirBar')
import Bar
假设您的两个目录都是真正的Python包(其中确实包含__init__.py文件),这里有一个相对于脚本位置包含模块的安全解决方案。
我假设您想这样做,因为您需要在脚本中包含一组模块。我在一些产品的生产中使用了这一点,并在许多特殊场景中工作,例如:从另一个目录调用或使用python执行的脚本,而不是打开新的解释器。
import os, sys, inspect
# realpath() will make your script run, even if you symlink it :)
cmd_folder = os.path.realpath(os.path.abspath(os.path.split(inspect.getfile( inspect.currentframe() ))[0]))
if cmd_folder not in sys.path:
sys.path.insert(0, cmd_folder)
# Use this if you want to include modules from a subfolder
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"subfolder")))
if cmd_subfolder not in sys.path:
sys.path.insert(0, cmd_subfolder)
# Info:
# cmd_folder = os.path.dirname(os.path.abspath(__file__)) # DO NOT USE __file__ !!!
# __file__ fails if the script is called in different ways on Windows.
# __file__ fails if someone does os.chdir() before.
# sys.argv[0] also fails, because it doesn't not always contains the path.
另外,这种方法允许您强制Python使用您的模块,而不是安装在系统上的模块。
警告我真的不知道当当前模块在蛋文件中时会发生什么。它可能也会失败。
以下是使用相对路径从上面的一个级别导入文件的方法。
基本上,只需将工作目录向上移动一个级别(或任何相对位置),将其添加到路径中,然后将工作目录移回其起始位置。
#to import from one level above:
cwd = os.getcwd()
os.chdir("..")
below_path = os.getcwd()
sys.path.append(below_path)
os.chdir(cwd)
我对python没有经验,所以如果我的话有任何错误,请告诉我。如果您的文件层次结构是这样安排的:
project\
module_1.py
module_2.py
module_1.py定义了一个名为func_1()的函数,module_2.py:
from module_1 import func_1
def func_2():
func_1()
if __name__ == '__main__':
func_2()
如果在cmd中运行python module_2.py,它将运行func1()定义的内容。这通常是我们导入相同层次结构文件的方式。但当您从module_2.py中的.module_1 import func_1写入时,python解释器将显示No module named'__main__.module_1';'__main__'不是包。因此,为了解决这个问题,我们只需保留刚才所做的更改,并将两个模块移动到一个包中,然后将第三个模块作为调用方运行module_2.py。
project\
package_1\
module_1.py
module_2.py
main.py
main.py:
from package_1.module_2 import func_2
def func_3():
func_2()
if __name__ == '__main__':
func_3()
但我们添加一个。在module_2.py中的module_1之前,如果我们不这样做并运行main.py,python解释器会说没有名为“module_1”的模块,这有点棘手,module_1.py就在module_.py旁边。现在我让module_1.y中的func_1()做一些事情:
def func_1():
print(__name__)
__name__记录谁调用func_1。现在我们保留。在module1之前,运行main.py,它将打印package1.module1,而不是module1。它表示调用func_1()的人与main.py位于同一层次结构中。暗示module1与module2.py本身处于同一层次结构。因此,如果没有点,main.py将在与自身相同的层次结构中识别模块_1,它可以识别package_1,但不能识别其下的内容。
现在让我们把它弄得有点复杂。您有一个config.ini,一个模块定义了一个函数,以便在与“main.py”相同的层次结构中读取它。
project\
package_1\
module_1.py
module_2.py
config.py
config.ini
main.py
由于某些不可避免的原因,您必须使用module_2.py调用它,因此它必须从上层导入module_2.py:
import ..config
pass
两个点表示从上层导入(三个点访问上层,而不是上层,依此类推)。现在我们运行main.py,解释器会说:ValueError:试图在顶级包之外进行相对导入。这里的“顶级包”是main.py。正因为config.py在main.py的旁边,所以它们处于相同的层次结构中,config.py不是“在”main.py之下,或者它不是由main.py“引导”的,所以它超出了main.py之外。要解决这个问题,最简单的方法是:
project\
package_1\
module_1.py
module_2.py
config.py
config.ini
main.py
我认为这符合排列项目文件层次结构的原则,您应该在不同的文件夹中排列具有不同功能的模块,只需在外部保留一个顶级调用程序,您就可以随意导入。