从相对路径导入模块
如何在给定相对路径的情况下导入 Python 模块?
例如,如果 dirFoo
包含 Foo.py
和 dirBar
,并且 dirBar
包含 Bar.py< /code>,如何将
Bar.py
导入到 Foo.py
中?
下面是一个直观的表示:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
希望包含 Bar
,但重组文件夹层次结构不是一个选项。
How do I import a Python module given its relative path?
For example, if dirFoo
contains Foo.py
and dirBar
, and dirBar
contains Bar.py
, how do I import Bar.py
into Foo.py
?
Here's a visual representation:
dirFoo\
Foo.py
dirBar\
Bar.py
Foo
wishes to include Bar
, but restructuring the folder hierarchy is not an option.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(22)
假设您的两个目录都是真正的 Python 包(其中确实有 __init__.py 文件),这里有一个安全的解决方案,用于包含相对于脚本位置的模块。
我假设您想要这样做,因为您需要在脚本中包含一组模块。 我在多个产品的生产中使用它,并在许多特殊场景中工作,例如:从另一个目录调用脚本或使用 python 执行执行脚本,而不是打开新的解释器。
作为奖励,这种方法确实可以让你强制 Python 使用你的模块而不是系统上安装的模块。
警告! 我真的不知道当当前模块位于 Egg 文件中时会发生什么。 大概也会失败吧。
Assuming that both your directories are real Python packages (do have the
__init__.py
file inside them), here is a safe solution for inclusion of modules relatively to the location of the script.I assume that you want to do this, because you need to include a set of modules with your script. I use this in production in several products and works in many special scenarios like: scripts called from another directory or executed with python execute instead of opening a new interpreter.
As a bonus, this approach does let you force Python to use your module instead of the ones installed on the system.
Warning! I don't really know what is happening when current module is inside an
egg
file. It probably fails too.确保 dirBar 具有
__init__.py
文件——这会将目录放入 Python 包中。Be sure that dirBar has the
__init__.py
file -- this makes a directory into a Python package.您还可以将该子目录添加到 Python 路径中,以便将其作为普通脚本导入。
You could also add the subdirectory to your Python path so that it imports as a normal script.
只需执行简单的操作即可从不同的文件夹导入 .py 文件。
假设您有一个类似的目录:
然后只需在 lib 文件夹中保留一个名为的空文件
然后使用
在导入模块层次结构的每个文件夹中保留
__init__.py
文件。Just do simple things to import the .py file from a different folder.
Let's say you have a directory like:
Then just keep an empty file in lib folder as named
And then use
Keep the
__init__.py
file in every folder of the hierarchy of the import module.如果您以这种方式构建您的项目:
那么从 Foo.py 您应该能够执行以下操作:
或者:
根据 Tom 的评论,这确实要求可以通过
site_packagessrc
文件夹code> 或您的搜索路径。 此外,正如他提到的,当您第一次在该包/目录中导入模块时,__init__.py
会被隐式导入。 通常__init__.py
只是一个空文件。If you structure your project this way:
Then from Foo.py you should be able to do:
Or:
Per Tom's comment, this does require that the
src
folder is accessible either viasite_packages
or your search path. Also, as he mentions,__init__.py
is implicitly imported when you first import a module in that package/directory. Typically__init__.py
is simply an empty file.这是相关的 PEP:
http://www.python.org/dev/peps /pep-0328/
特别是,假设 dirFoo 是 dirBar 之上的目录...
在 dirFoo\Foo.py 中:
This is the relevant PEP:
http://www.python.org/dev/peps/pep-0328/
In particular, presuming dirFoo is a directory up from dirBar...
In dirFoo\Foo.py:
最简单的方法是使用 sys.path.append()。
但是,您可能还对 imp 模块感兴趣。
它提供对内部导入功能的访问。
当您不知道模块名称时,这可用于动态加载模块。
我过去曾使用它来创建应用程序的插件类型接口,用户可以在其中编写具有应用程序特定功能的脚本,然后将其脚本放入特定目录中。
此外,这些功能可能很有用:
The easiest method is to use sys.path.append().
However, you may be also interested in the imp module.
It provides access to internal import functions.
This can be used to load modules dynamically when you don't know a module's name.
I've used this in the past to create a plugin type interface to an application, where the user would write a script with application specific functions, and just drop thier script in a specific directory.
Also, these functions may be useful:
无需对脚本进行任何修改的最简单方法是设置 PYTHONPATH 环境变量。 因为 sys.path 是从这些位置初始化的:
目录)。
语法与 shell 变量 PATH 相同)。
只需运行:
您的 sys.path 将包含上述路径,如下所示:
The easiest way without any modification to your script is to set PYTHONPATH environment variable. Because sys.path is initialized from these locations:
directory).
syntax as the shell variable PATH).
Just run:
You sys.path will contains above path, as show below:
在我看来,最好的选择是将 __ init __.py 放在文件夹中并使用 调用该文件。
不建议使用 sys.path.append() 因为如果使用可能会出现问题与现有 python 包的文件名相同。 我还没有测试过,但这会很模糊。
In my opinion the best choice is to put __ init __.py in the folder and call the file with
It is not recommended to use sys.path.append() because something might gone wrong if you use the same file name as the existing python package. I haven't test that but that will be ambiguous.
而不是:
以防万一可能安装了另一个 dirBar 并使 foo.py 读者感到困惑。
instead of:
just in case there could be another dirBar installed and confuse a foo.py reader.
对于将 Bar.py 导入到 Foo.py 的情况,首先我会将这些文件夹转换为 Python 包,如下所示:
然后我会在 Foo.py 中这样做:
如果我希望命名空间看起来像 Bar.whatever,或者
如果我想要命名空间 dirBar.Bar。whatever。 如果 dirBar 包下有更多模块,则第二种情况很有用。
For this case to import Bar.py into Foo.py, first I'd turn these folders into Python packages like so:
Then I would do it like this in Foo.py:
If I wanted the namespacing to look like Bar.whatever, or
If I wanted the namespacing dirBar.Bar.whatever. This second case is useful if you have more modules under the dirBar package.
对于 Linux 用户来说,快速而肮脏的方法
如果您只是在修修补补并且不关心部署问题,您可以使用符号链接(假设您的文件系统支持它)使模块或包在以下文件夹中直接可见请求模块。
或
注意:“模块”是任何具有 .py 扩展名的文件,“包”是包含文件
__init__.py
(可以是空文件)的任何文件夹。 从使用的角度来看,模块和包是相同的 - 都根据import
命令的请求公开其包含的“定义和语句”。请参阅:http://docs.python.org/2/tutorial/modules.html
The quick-and-dirty way for Linux users
If you are just tinkering around and don't care about deployment issues, you can use a symbolic link (assuming your filesystem supports it) to make the module or package directly visible in the folder of the requesting module.
or
Note: A "module" is any file with a .py extension and a "package" is any folder that contains the file
__init__.py
(which can be an empty file). From a usage standpoint, modules and packages are identical -- both expose their contained "definitions and statements" as requested via theimport
command.See: http://docs.python.org/2/tutorial/modules.html
添加 __init__.py 文件:
然后将此代码添加到 Foo.py 的开头:
Add an __init__.py file:
Then add this code to the start of Foo.py:
相对 sys.path 示例:
基于这个答案。
Relative sys.path example:
Based on this answer.
另一种解决方案是安装 py-require 包,然后在
Foo.py
Another solution would be to install the py-require package and then use the following in
Foo.py
好吧,正如您所提到的,通常您希望访问包含相对于主脚本运行位置的模块的文件夹,因此您只需导入它们即可。
解决方案:
我的脚本位于 D:/Books/MyBooks.py 和一些模块(如 oldies.py)中。 我需要从子目录
D:/Books/includes
导入:将
print('done')
放入oldies.py
中,以便验证一切都很顺利。 这种方式总是有效,因为根据程序启动时初始化的 Python 定义sys.path
,此列表的第一项path[0]
是包含脚本的目录用于调用 Python 解释器。如果脚本目录不可用(例如,如果交互调用解释器或从标准输入读取脚本),则
path[0]
为空字符串,它指示 Python 在目录中搜索模块。首先是当前目录。 请注意,脚本目录被插入到由于PYTHONPATH
而插入的条目之前。Well, as you mention, usually you want to have access to a folder with your modules relative to where your main script is run, so you just import them.
Solution:
I have the script in
D:/Books/MyBooks.py
and some modules (like oldies.py). I need to import from subdirectoryD:/Books/includes
:Place a
print('done')
inoldies.py
, so you verify everything is going OK. This way always works because by the Python definitionsys.path
as initialized upon program startup, the first item of this list,path[0]
, is the directory containing the script that was used to invoke the Python interpreter.If the script directory is not available (e.g. if the interpreter is invoked interactively or if the script is read from standard input),
path[0]
is the empty string, which directs Python to search modules in the current directory first. Notice that the script directory is inserted before the entries inserted as a result ofPYTHONPATH
.只需使用:
from Desktop.filename import some
示例:
代码:
但请确保在该目录中创建一个名为“
__init__.py
”的空文件Simply you can use:
from Desktop.filename import something
Example:
the code:
But make sure you make an empty file called "
__init__.py
" in that directory这是使用相对路径从上一级导入文件的方法。
基本上,只需将工作目录向上移动一个级别(或任何相对位置),将其添加到您的路径中,然后将工作目录移回其开始位置。
Here's a way to import a file from one level above, using the relative path.
Basically, just move the working directory up a level (or any relative location), add that to your path, then move the working directory back where it started.
我对python没有什么经验,所以如果我的话有什么错误,请告诉我。 如果您的文件层次结构如下排列:
module_1.py
定义了一个名为func_1()
的函数,module_2.py:并且您运行
python module_2.py
在 cmd 中,它将运行func_1()
定义的内容。 这通常是我们导入相同层次结构文件的方式。 但是当你在module_2.py
中编写from .module_1 import func_1
时,Python解释器会说No module named '__main__.module_1'; '__main__' 不是一个包
。 因此,为了解决这个问题,我们只需保留刚刚所做的更改,并将两个模块移动到一个包中,然后将第三个模块作为调用者来运行module_2.py
。main.py:
但是我们在
module_2.py
中的module_1
之前添加.
的原因是,如果我们不这样做不要这样做并运行main.py
,Python 解释器会说No module named 'module_1'
,这有点棘手,module_1.py
就在module_2.py
旁边。 现在,我让module_1.py
中的func_1()
执行一些操作:__name__
记录谁调用了 func_1。 现在我们将.
保留在module_1
之前,运行main.py
,它会打印package_1.module_1
,而不是 <代码> module_1 。 它表明调用func_1()
的人与main.py
处于同一层次结构,.
暗示module_1< /code> 与 module_2.py 本身处于同一层次结构。 因此,如果没有点,
main.py
将识别与其自身处于同一层次结构的module_1
,它可以识别package_1
,但不能识别它“下面”是什么。现在让我们把它变得复杂一点。 您有一个 config.ini,并且模块定义了一个函数,可以在与“main.py”相同的层次结构中读取它。
由于某些不可避免的原因,您必须使用
module_2.py
来调用它,因此它必须从上层导入。module_2.py:两个点表示从上层导入(三个点访问上比上,依此类推)。 现在我们运行
main.py
,解释器会说:ValueError:尝试相对导入超出顶级包
。 这里的“顶级包”是main.py
。 只是因为config.py
位于main.py
旁边,它们处于同一层次结构,config.py
不在“下”main.py
,或者它不是由main.py
“引导”,因此它超出了main.py
。 要解决这个问题,最简单的方法是:我认为这符合安排项目文件层次结构的原则,您应该将不同功能的模块安排在不同的文件夹中,并且只在外面留下一个顶级调用者,然后您可以导入你要。
I'm not experienced about python, so if there is any wrong in my words, just tell me. If your file hierarchy arranged like this:
module_1.py
defines a function calledfunc_1()
, module_2.py:and you run
python module_2.py
in cmd, it will do run whatfunc_1()
defines. That's usually how we import same hierarchy files. But when you writefrom .module_1 import func_1
inmodule_2.py
, python interpreter will sayNo module named '__main__.module_1'; '__main__' is not a package
. So to fix this, we just keep the change we just make, and move both of the module to a package, and make a third module as a caller to runmodule_2.py
.main.py:
But the reason we add a
.
beforemodule_1
inmodule_2.py
is that if we don't do that and runmain.py
, python interpreter will sayNo module named 'module_1'
, that's a little tricky,module_1.py
is right besidemodule_2.py
. Now I letfunc_1()
inmodule_1.py
do something:that
__name__
records who calls func_1. Now we keep the.
beforemodule_1
, runmain.py
, it will printpackage_1.module_1
, notmodule_1
. It indicates that the one who callsfunc_1()
is at the same hierarchy asmain.py
, the.
imply thatmodule_1
is at the same hierarchy asmodule_2.py
itself. So if there isn't a dot,main.py
will recognizemodule_1
at the same hierarchy as itself, it can recognizepackage_1
, but not what "under" it.Now let's make it a bit complicated. You have a
config.ini
and a module defines a function to read it at the same hierarchy as 'main.py'.And for some unavoidable reason, you have to call it with
module_2.py
, so it has to import from upper hierarchy.module_2.py:Two dots means import from upper hierarchy (three dots access upper than upper,and so on). Now we run
main.py
, the interpreter will say:ValueError:attempted relative import beyond top-level package
. The "top-level package" at here ismain.py
. Just becauseconfig.py
is besidemain.py
, they are at same hierarchy,config.py
isn't "under"main.py
, or it isn't "leaded" bymain.py
, so it is beyondmain.py
. To fix this, the simplest way is:I think that is coincide with the principle of arrange project file hierarchy, you should arrange modules with different function in different folders, and just leave a top caller in the outside, and you can import how ever you want.
这也有效,并且比使用
sys
模块的任何内容都简单得多:This also works, and is much simpler than anything with the
sys
module:你可以说我过于谨慎,但我喜欢让我的文件更加便携,因为假设文件在每台计算机上总是位于同一位置是不安全的。 就我个人而言,我让代码首先查找文件路径。 我使用 Linux,所以我的看起来像这样:
当然,除非你打算将它们打包在一起。 但如果是这种情况,您实际上并不需要两个单独的文件。
Call me overly cautious, but I like to make mine more portable because it's unsafe to assume that files will always be in the same place on every computer. Personally I have the code look up the file path first. I use Linux so mine would look like this:
That is of course unless you plan to package these together. But if that's the case you don't really need two separate files anyway.