Importing files from different folder
我有以下文件夹结构。
我想从另一个python文件中的file.py导入一些函数,该文件位于
我试过了
还有其他各种各样的尝试,但到目前为止,我还无法正确导入。我该怎么做?
默认情况下,您不能这样做。导入文件时,python只搜索当前目录、运行入口点脚本的目录,以及
但是,您可以在运行时添加到python路径:
1 2 3 4 5 | # some_file.py import sys sys.path.insert(0, '/path/to/application/app/folder') import file |
没有问题:
1 | from application.app.folder.file import func_name |
只要确保
当模块处于平行位置时,如问题所示:
1 2 | application/app2/some_folder/some_file.py application/app2/another_folder/another_file.py |
此速记使一个模块对另一个模块可见:
1 2 | import sys sys.path.append('../') |
我认为一种特别的方法是使用环境变量
1 2 3 4 5 | # Linux & OSX export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH # Windows set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH% |
这里的答案不够清晰,这是在Python3.6上测试的。
使用此文件夹结构:
1 2 3 | main.py | ---- myfolder/myfile.py |
其中,
1 2 | def myfunc(): print('hello') |
1 2 | from myfolder.myfile import myfunc myfunc() |
这将打印"你好"。
您的问题是,python正在python目录中查找这个文件,但没有找到它。您必须指定您正在谈论的是您所在的目录,而不是python目录。
要执行此操作,请更改:
对此:
1 | from .application.app.folder.file import func_name |
通过添加点,您将在这个文件夹中查找应用程序文件夹,而不是在python目录中查找。
第一个导入系统
1 | import sys |
第二个附加文件夹路径
1 | sys.path.insert(0, '/the/folder/path/name-folder/') |
第三,在子目录中创建一个名为uuuinit uuuy.py的空白文件(这告诉python它是一个模块)
- NAME-FIL.PY
- 名称文件夹
- γ-π
- 名称模块
- 名称文件夹
第四,导入文件夹中的模块
1 | from name-folder import name-module |
据我所知,直接在要导入的函数的文件夹中添加一个
将
1 2 3 4 5 | import sys sys.path.insert(0, r'/from/root/directory/application') from application.app.folder.file import func_name ## You can also use '*' wildcard to import all the functions in file.py file. func_name() |
在Linux上的python3为我工作
1 2 3 | import sys sys.path.append(pathToFolderContainingScripts) from scriptName import functionName #scriptName without .py extension |
尝试python的相对导入:
1 | from ...app.folder.file import func_name |
每个前导点都是从当前目录开始的层次结构中的另一个更高级别。
问题?如果这对你不起作用,那么你可能会被很多gotcha的相对进口产品所咬。阅读答案和评论了解更多详细信息:如何修复"尝试在非包中进行相对导入",即使使用uu init_uuy.py
提示:在每个目录级别都有
这在Windows上对我有效
1 2 3 4 5 | # some_file.py on mainApp/app2 import sys sys.path.insert(0, sys.path[0]+'\\app2') import some_file |
将应用程序移动到其他环境时,使用带有绝对路径的sys.path.append并不理想。使用相对路径并不总是有效,因为当前工作目录取决于如何调用脚本。
由于应用程序文件夹结构是固定的,因此我们可以使用os.path获取希望导入的模块的完整路径。例如,如果这是结构:
1 2 | /home/me/application/app2/some_folder/vanilla.py /home/me/application/app2/another_folder/mango.py |
假设您要导入"芒果"模块。您可以在vanilla.py中执行以下操作:
1 2 3 4 5 | import sys, os.path mango_dir = (os.path.abspath(os.path.join(os.path.dirname(__file__), '..')) + '/another_folder/') sys.path.append(mango_dir) import mango |
当然,您不需要mango_dir变量。
要了解这是如何工作的,请查看此交互式会话示例:
1 2 3 4 5 6 7 8 9 10 | >>> import os >>> mydir = '/home/me/application/app2/some_folder' >>> newdir = os.path.abspath(os.path.join(mydir, '..')) >>> newdir '/home/me/application/app2' >>> newdir = os.path.abspath(os.path.join(mydir, '..')) + '/another_folder' >>> >>> newdir '/home/me/application/app2/another_folder' >>> |
并查看os.path文档。
我面临着同样的挑战,尤其是在导入多个文件时,这就是我如何克服它的方法。
1 2 3 4 5 6 | import os, sys from os.path import dirname, join, abspath sys.path.insert(0, abspath(join(dirname(__file__), '..'))) from root_folder import file_name |
我很特别:我在Windows中使用python!
我只需要完成信息:对于Windows和Linux,相对路径和绝对路径都可以在
当使用windows时,
1 2 3 4 | sys.path.append('c:\\tools\\mydir') sys.path.append('..\\mytools') sys.path.append('c:/tools/mydir') sys.path.append('../mytools') |
(注:我认为
如果从特定路径加载模块的目的是帮助您开发自定义模块,则可以在指向自定义模块根的测试脚本的同一文件夹中创建符号链接。对于该文件夹中运行的任何脚本,此模块引用将优先于安装的任何其他同名模块。
我在Linux上测试过它,但是它应该可以在任何支持符号链接的现代操作系统中工作。
这种方法的一个优点是,您可以指向一个模块,该模块位于您自己的本地SVC分支工作副本中,它可以大大简化开发周期时间,并减少管理模块不同版本的失败模式。
在Python3.4及更高版本中,可以直接从源文件导入(链接到文档)。这不是最简单的解决方案,但为了完整性,我要包含这个答案。
下面是一个例子。首先,要导入的文件,名为
1 2 | def announce(): print("Imported!") |
导入上述文件的代码受到文档中示例的强烈启发:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import importlib.util def module_from_file(module_name, file_path): spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module foo = module_from_file("foo","/path/to/foo.py") if __name__ =="__main__": print(foo) print(dir(foo)) foo.announce() |
输出:
1 2 3 | <module 'foo' from '/path/to/foo.py'> ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce'] Imported! |
注意变量名、模块名和文件名不需要匹配。此代码仍然有效:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import importlib.util def module_from_file(module_name, file_path): spec = importlib.util.spec_from_file_location(module_name, file_path) module = importlib.util.module_from_spec(spec) spec.loader.exec_module(module) return module baz = module_from_file("bar","/path/to/foo.py") if __name__ =="__main__": print(baz) print(dir(baz)) baz.announce() |
输出:
1 2 3 | <module 'bar' from '/path/to/foo.py'> ['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce'] Imported! |
python 3.1中引入了以编程方式导入模块,使您能够更好地控制模块的导入方式。有关更多信息,请参阅文档。
您可以按F5刷新python shell,或者转到run->run模块。这样就不必更改目录来读取文件中的内容。python将自动更改目录。但是,如果您想在python shell中处理来自不同目录的不同文件,那么您可以在sys中更改目录,如Cameron前面所说。
在我的例子中,我有一个类要导入。我的文件如下:
1 2 3 | # /opt/path/to/code/log_helper.py class LogHelper: # stuff here |
在我的主文件中,我通过以下方式包含了代码:
1 2 | path.append("/opt/path/to/code/") from log_helper import LogHelper |
所以我刚刚右键点击了我的IDE,添加了一个新的
1 | sys.path.insert(0, '/path/to/application/app/folder') |