从不同文件夹导入文件
我有这样的文件夹结构:
application
├── app
│ └── folder
│ └── file.py
└── app2
└── some_folder
└── some_file.py
How can I import a function from file.py
, from inside some_file.py
?我尝试过:
from application.app.folder.file import func_name
但不起作用。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(30)
注意:这个答案是针对一个非常具体的问题。对于大多数从搜索引擎来到这里的程序员来说,这不是您正在寻找的答案。通常,您会将文件构建为包(请参阅其他答案),而不是修改搜索路径。
默认情况下,你不能。导入文件时,Python 仅搜索运行入口点脚本的目录和 sys.path,其中包括包安装目录等位置(实际上是 比这更复杂一点,但这涵盖了大多数情况)。
但是,您可以在运行时添加到 Python 路径:
Note: This answer was intended for a very specific question. For most programmers coming here from a search engine, this is not the answer you are looking for. Typically you would structure your files into packages (see other answers) instead of modifying the search path.
By default, you can't. When importing a file, Python only searches the directory that the entry-point script is running from and
sys.path
which includes locations such as the package installation directory (it's actually a little more complex than this, but this covers most cases).However, you can add to the Python path at runtime:
没有什么问题:
只要确保
folder
还包含__init__.py
即可。这使得它可以作为一个包包含在内。我不确定为什么其他答案谈论PYTHONPATH
。There is nothing wrong with:
Just make sure
folder
also contains an__init__.py
. This allows it to be included as a package. I am not sure why the other answers talk aboutPYTHONPATH
.当模块位于并行位置时,如问题所示:
此简写使一个模块对另一个模块可见:
When modules are in parallel locations, as in the question:
This shorthand makes one module visible to the other:
第一 在 name-file.py 中导入 sys
第二 在 name-file.py 中附加文件夹路径
第三 创建一个名为 __ init __ 的空白文件.py 在你的子目录中(这告诉 Python 它是一个包)
第四次导入name-file.py文件夹内的模块
First import sys in name-file.py
Second append the folder path in name-file.py
Third Make a blank file called __ init __.py in your subdirectory (this tells Python it is a package)
Fourth import the module inside the folder in name-file.py
尝试 Python 的相对导入:
每个前导点都是从当前目录开始的层次结构中的另一个更高级别。
有问题吗?如果这对你不起作用,那么你可能会被许多相对导入的陷阱所困扰。
阅读答案和评论以获取更多详细信息:
如何修复“尝试相对import in non-package”,即使使用 __init__.py
提示:在每个目录级别都有
__init__.py
。您可能需要从顶级目录运行的 python -m application.app2.some_folder.some_file (不包括 .py),或者在 PYTHONPATH 中拥有该顶级目录。 唷!Try Python's relative imports:
Every leading dot is another higher level in the hierarchy beginning with the current directory.
Problems? If this isn't working for you then you probably are getting bit by the many gotcha's relative imports has.
Read answers and comments for more details:
How to fix "Attempted relative import in non-package" even with __init__.py
Hint: have
__init__.py
at every directory level. You might needpython -m application.app2.some_folder.some_file
(leaving off .py) which you run from the top level directory or have that top level directory in your PYTHONPATH. Phew!我认为一种临时方法是使用 环境变量
PYTHONPATH
如文档中所述:Python2, Python3I think an ad hoc way would be to use the environment variable
PYTHONPATH
as described in the documentation: Python2, Python3问题是 Python 在错误的目录中查找该文件。要解决此问题,请尝试使用相对导入。更改
为:
添加点指示 Python 在当前文件夹中查找
application
文件夹,而不是在 Python 安装文件夹中查找。The issue is that Python is looking in the wrong directory for the file. To solve this, try using relative import. Change
to:
Adding the dot instructs Python to look for the
application
folder within the current folder, instead of in the Python install folder.给定一个文件夹结构,如
其中
myfile.py
包含要从
main.py
调用myfunc
,请使用:Given a folder structure like
Where
myfile.py
containsTo call
myfunc
frommain.py
, use:在 Python 3.4 及更高版本中,您可以从直接源文件(链接到文档)。这不是最简单的解决方案,但为了完整性我将这个答案包括在内。
这是一个例子。首先,要导入的文件,名为 foo.py:
导入上面文件的代码,很大程度上受到文档中示例的启发:
输出:
请注意变量名称,模块名称,并且文件名不需要匹配。此代码仍然有效:
输出:
Python 3.1 中引入了以编程方式导入模块,使您可以更好地控制模块的导入方式。请参阅文档以获取更多信息。
In Python 3.4 and later, you can import from a source file directly (link to documentation). This is not the simplest solution, but I'm including this answer for completeness.
Here is an example. First, the file to be imported, named
foo.py
:The code that imports the file above, inspired heavily by the example in the documentation:
The output:
Note that the variable name, the module name, and the filename need not match. This code still works:
The output:
Programmatically importing modules was introduced in Python 3.1 and gives you more control over how modules are imported. Refer to the documentation for more information.
将应用程序移动到其他环境时,使用带有绝对路径的 sys.path.append 并不理想。使用相对路径并不总是有效,因为当前工作目录取决于脚本的调用方式。
由于应用程序文件夹结构是固定的,我们可以使用 os.path 来获取我们想要导入的模块的完整路径。例如,如果结构如下:
假设您要导入 mango 模块。您可以在 vanilla.py 中执行以下操作:
当然,您不需要 mango_dir 变量。
要了解其工作原理,请查看此交互式会话示例:
并检查 os.path< /a> 文档。
另外值得注意的是,使用 packages 时,处理多个文件夹会变得更加容易,因为可以使用点模块名称。
Using
sys.path.append
with an absolute path is not ideal when moving the application to other environments. Using a relative path won't always work because the current working directory depends on how the script was invoked.Since the application folder structure is fixed, we can use
os.path
to get the full path of the module we wish to import. For example, if this is the structure:And let's say that you want to import the mango module. You could do the following in vanilla.py:
Of course, you don't need the mango_dir variable.
To understand how this works look at this interactive session example:
And check the os.path documentation.
Also worth noting that dealing with multiple folders is made easier when using packages, as one can use dotted module names.
据我所知,直接在要导入的函数的文件夹中添加一个
__init__.py
文件即可完成这项工作。From what I know, add an
__init__.py
file directly in the folder of the functions you want to import will do the job.我面临着同样的挑战,特别是在导入多个文件时,这就是我设法克服它的方法。
I was faced with the same challenge, especially when importing multiple files, this is how I managed to overcome it.
这在 Linux 上的 Python 3 中对我有用:
This worked for me in Python 3 on Linux:
将
application
视为 Python 项目的根目录,在application
、app
中创建一个空的__init__.py
文件> 和folder
文件夹。然后在some_file.py
中进行如下更改以获取 func_name 的定义:Considering
application
as the root directory for your Python project, create an empty__init__.py
file in theapplication
,app
andfolder
folders. Then in yoursome_file.py
, make changes as follows to get the definition of func_name:您可以将父目录添加到
PYTHONPATH
,为了实现这一点,您可以在sys.path
中列出的“模块搜索路径”中使用取决于操作系统的路径。因此,您可以轻松添加父目录,如下所示:You can add the parent directory to
PYTHONPATH
, in order to achieve that, you can use OS depending path in the "module search path" which is listed insys.path
. So you can easily add the parent directory like following:一种方法是创建一个包并使用绝对导入来访问该包中的其他模块。从包根目录下的脚本启动程序。这种结构允许使用和访问子包、父包以及同级包和模块。
例如,尝试创建以下文件夹结构:
main_module.py
的内容:module_0.py
的内容:module_1.py
的内容:module_2.py
的内容:module_3.py
的内容:将所有
__init__.py
文件留空。现在运行main_module.py;输出将是
One way is to create a package and use absolute import to access other modules from the package. Start the program from a script at the root of the package. This structure allows using and accessing sub-packages, parent package, and sibling packages and modules.
As an example, try creating the following folder structure:
Contents of
main_module.py
:Contents of
module_0.py
:Contents of
module_1.py
:Contents of
module_2.py
:Contents of
module_3.py
:Leave all
__init__.py
files empty.Now run
main_module.py
; the output will be就我而言,我有一个类要导入。我的文件如下所示:
在我的主文件中,我通过以下方式包含了代码:
In my case I had a class to import. My file looked like this:
In my main file I included the code via:
这对我在 Windows 上有效:
This works for me on Windows:
我多次遇到同样的问题,所以我想分享我的解决方案。
Python 版本:3.X
以下解决方案适用于在 Python 版本 3.X 中开发应用程序的人员,因为 自 2020 年 1 月 1 日起不再支持 Python 2。
项目结构
在 python 3 中,由于 隐式命名空间包。请参阅是init Python 3.3+ 中的包不需要 .py
问题陈述
在
file_b.py
中,我想在file_a.py 中导入类
在文件夹a下。A
解决方案
#1 一种快速但肮脏的方法
无需安装软件包,就像您当前正在开发一个新项目一样
使用
try catch
检查是否有错误。代码示例:#2 安装你的包
一旦你安装了你的应用程序(在这篇文章中,不包括安装教程),
你就可以简单地
快乐编码!
I bumped into the same question several times, so I would like to share my solution.
Python Version: 3.X
The following solution is for someone who develops your application in Python version 3.X because Python 2 is not supported since Jan/1/2020.
Project Structure
In python 3, you don't need
__init__.py
in your project subdirectory due to the Implicit Namespace Packages. See Is init.py not required for packages in Python 3.3+Problem Statement
In
file_b.py
, I would like to import a classA
infile_a.py
under the folder a.Solutions
#1 A quick but dirty way
Without installing the package like you are currently developing a new project
Using the
try catch
to check if the errors. Code example:#2 Install your package
Once you installed your application (in this post, the tutorial of installation is not included)
You can simply
Happy coding!
我很特别:我在 Windows 上使用 Python!
我只是完成信息:对于 Windows 和 Linux,相对路径和绝对路径都适用于 sys.path(我需要相对路径,因为我在多台 PC 上和不同的主目录下使用我的脚本)。
当使用 Windows 时,
\
和/
都可以用作文件名的分隔符,当然你必须将\
复制到 Python 字符串中。以下是一些有效的示例:(注意:我认为
/
比\
更方便,即使它不太“Windows 原生”,因为它是 Linux 兼容的并且更容易编写并复制到 Windows 资源管理器)I'm quite special: I use Python with Windows!
I just complete information: for both Windows and Linux, both relative and absolute paths work into
sys.path
(I need relative paths because I use my scripts on the several PCs and under different main directories).And when using Windows, both
\
and/
can be used as a separator for file names and of course you must double\
into Python strings. Here are some valid examples:(Note: I think that
/
is more convenient than\
, even if it is less 'Windows-native', because it is Linux-compatible and simpler to write and copy to Windows Explorer)以下内容对我有用:
操作系统:Windows 10
Python:v3.10.0
注意:由于我是Python v3.10.0,所以我没有使用
__init__.py
文件,无论如何这对我不起作用。WY Hsu的第一个解决方案对我有用。为了清楚起见,我用绝对文件引用重新发布了它:
替代解决方案:但是,这也对我有用:
虽然,我不明白它为什么有效。我认为点是对当前目录的引用。但是,当打印当前文件夹的路径时,当前目录已列在顶部:
The following worked for me:
OS: Windows 10
Python: v3.10.0
Note: Since I am Python v3.10.0, I am not using
__init__.py
files, which did not work for me anyway.WY Hsu's first solution worked for me. I have reposted it with an absolute file reference for clarity:
Alternative Solution: However, this also worked for me:
Although, I do not understand why it works. I thought the dot is a reference to the current directory. However, when printing out the paths to the current folder, the current directory is already listed at the top:
不要仅仅执行
导入...
,而是执行以下操作:from import
MyFile 位于 MySubFolder 内。
Instead of just doing an
import ...
, do this :from <MySubFolder> import <MyFile>
MyFile is inside the MySubFolder.
我正在开发项目
a
,我希望用户通过pip install a
安装该项目,其中包含以下文件列表:setup.py
MANIFEST.in
a/init.py
a/a.py
a/b/init.py
a/b/b.py
我通过从
MANIFEST.in:
然后,从我的文件系统
/moustache/armwrestle
上的一个完全不同的位置运行:这证实了
a.cats
确实等于 0 和正如预期的那样,abdogs
确实等于 1。I was working on project
a
that I wanted users to install viapip install a
with the following file list:setup.py
MANIFEST.in
a/init.py
a/a.py
a/b/init.py
a/b/b.py
I installed the module by running the following from the directory with
MANIFEST.in
:Then, from a totally different location on my filesystem
/moustache/armwrestle
I was able to run:Which confirmed that
a.cats
indeed equalled 0 anda.b.dogs
indeed equalled 1, as intended.我的解决方案适用于包中包含所有必要的
__init__.py
的人,但导入仍然不起作用。My solution for people who have all the necessary
__init__.py
in the package, but import still doesn't work.已经有很多其他解决方案,但这是我的两分钱。假设您不想执行以下任何操作:
__init__.py
filespython -m mymodule
__package__
if
签入__main__
sys.path
PYTHONPATH
您可以使用一个工具来代替将向 sys.path 添加给定的绝对/相对路径,同时确保路径有效且格式正确。
$ pip install importmonkey
[github] [pip]隶属关系披露:我制作了 importmonkey。
There are plenty of other solutions already but here is my two cents. Let's say you don't want to do any of these:
__init__.py
filespython -m mymodule
__package__
if
check in__main__
sys.path
by handPYTHONPATH
You can instead use a tool that will that will add a given absolute/relative path to sys.path while making sure the path is valid and in the correct format.
$ pip install importmonkey
[github] [pip]Disclosure of affiliation: I made importmonkey.
下面的代码以 Python 版本安全的方式导入由其路径给出的 Python 脚本,无论它位于何处:
我在 psutils,位于
psutils.test.__init__.py
(截至 2020 年 10 月 9 日的最新提交)。使用示例:
重要警告:该模块将被视为顶级模块;从其中的父包进行任何相对导入都会失败。
The code below imports the Python script given by its path, no matter where it is located, in a Python version-safe way:
I found this in the codebase of psutils, at line 1042 in
psutils.test.__init__.py
(most recent commit as of 09.10.2020).Usage example:
Important caveat: The module will be treated as top-level; any relative imports from parent packages in it will fail.
这对我有用。
Python 将包含您启动的脚本的文件夹添加到 PYTHONPATH,因此,如果您运行,
则仅将文件夹 application/app2/some_folder 添加到路径(而不是您的基本目录)重新执行中的命令)。相反,将文件作为模块运行,并在 some_folder 目录中添加 __init__.py 。
这会将基目录添加到可执行文件
python
的路径中,然后可以通过非相对导入来访问类。This worked for me.
Python adds the folder containing the script you launch to the PYTHONPATH, so if you run
Only the folder application/app2/some_folder is added to the path (not the base directory that you're executing the command in). Instead, run your file as a module and add a __init__.py in your some_folder directory.
This will add the base directory to the path to executable
python
, and then classes will be accessible via a non-relative import.如果从特定路径加载模块的目的是在开发自定义模块期间为您提供帮助,则可以在测试脚本的同一文件夹中创建一个符号链接,指向自定义模块的根目录。对于在该文件夹中运行的任何脚本,此模块引用将优先于安装的任何其他同名模块。
我在 Linux 上对此进行了测试,但它应该可以在任何支持符号链接的现代操作系统中工作。
这种方法的一个优点是,您可以指向位于您自己的本地软件版本控制分支工作副本中的模块,这可以大大简化开发周期时间并减少管理不同版本模块的故障模式。
If the purpose of loading a module from a specific path is to assist you during the development of a custom module, you can create a symbolic link in the same folder of the test script that points to the root of the custom module. This module reference will take precedence over any other modules installed of the same name for any script run in that folder.
I tested this on Linux but it should work in any modern OS that supports symbolic links.
One advantage to this approach is that you can you can point to a module that's sitting in your own local software version control branch working copy which can greatly simplify the development cycle time and reduce failure modes of managing different versions of the module.
您可以使用
pip
的pip install -e .
命令。您必须在项目目录的根目录中创建一个名为setup.py
的文件,其中包含以下内容:然后,在项目的根目录中输入
pip install -e .
。这将使所有目录能够以其名称作为模块来调用。例如,如果您的根目录包含子目录module1
和module2
,每个子目录中都包含脚本,您将能够使用以下命令从任何子目录访问它们:module1
:导入 module1.script1 作为 script1
You can use
pip
'spip install -e .
command. You must create a file calledsetup.py
in the root of the project's directory which contains the following:Afterwards, enter
pip install -e .
while in your project's root directory. This will enable all directories to be called with their name as a module. For example, if your root directory contains the subdirectoriesmodule1
andmodule2
, each with scripts inside them, you will be able to access them from any subdirectories with the following command, formodule1
:import module1.script1 as script1
这个问题可能是由于 PyCharm
我在使用 PyCharm 时遇到了同样的问题。我有这个项目结构
,并且 example.py 中的代码
from configuration import settings
引发了导入错误。问题是,当我打开 PyCharm 时,它认为 skylake 是根路径并运行此代码。
为了解决这个问题,我只是将后端目录标记为源根目录。
它解决了我的问题。
This problem may be due to PyCharm
I had the same problem while using PyCharm. I had this project structure
and code
from configuration import settings
in example.py raised an import error.The problem was that when I opened PyCharm, it considered that skylake is the root path and ran this code.
To fix this I just marked backend directory as the source root.
And it's fixed my problem.