Iva*_*van 1186 python python-import importerror
我有以下文件夹结构.
application/app/folder/file.py
我想从另一个驻留的Python文件中的file.py中导入一些函数
application/app2/some_folder/some_file.py
我试过了
from application.app.folder.file import func_name
和其他一些尝试,但到目前为止我无法正确导入.我怎样才能做到这一点?
Cam*_*ron 1253
默认情况下,你不能.导入文件时,Python只搜索当前目录,运行入口点脚本的目录,以及sys.path
包括安装目录在内的位置(实际上它比这更复杂,但这涵盖了大多数情况) .
但是,您可以在运行时添加到Python路径:
# some_file.py
import sys
# insert at 1, 0 is the script path (or '' in REPL)
sys.path.insert(1, '/path/to/application/app/folder')
import file
Run Code Online (Sandbox Code Playgroud)
joe*_*oey 614
没有错:
from application.app.folder.file import func_name
Run Code Online (Sandbox Code Playgroud)
只需确保文件夹中还包含__init__.py,这样就可以将其作为包包含在内.不知道为什么其他答案谈论PYTHONPATH.
sli*_*izb 83
当模块处于并行位置时,如问题所示:
application/app2/some_folder/some_file.py
application/app2/another_folder/another_file.py
Run Code Online (Sandbox Code Playgroud)
这个简写使一个模块对另一个模块可见:
import sys
sys.path.append('../')
Run Code Online (Sandbox Code Playgroud)
Ax3*_*x3l 50
我认为一种特殊的方式是使用文档中描述的环境变量PYTHONPATH
:Python2,Python3
# Linux & OSX
export PYTHONPATH=$HOME/dirWithScripts/:$PYTHONPATH
# Windows
set PYTHONPATH=C:\path\to\dirWithScripts\;%PYTHONPATH%
Run Code Online (Sandbox Code Playgroud)
Ale*_*oya 40
首先导入系统
import sys
Run Code Online (Sandbox Code Playgroud)
第二个附加文件夹路径
sys.path.insert(0, '/the/folder/path/name-folder/')
Run Code Online (Sandbox Code Playgroud)
三,在子目录中创建一个名为__ init __.py的空白文件(这告诉Python它是一个模块)
四,导入文件夹内的模块
from name-folder import name-module
Run Code Online (Sandbox Code Playgroud)
Cia*_*anB 35
您的问题是Python正在Python目录中查找此文件而未找到它.您必须指定您正在谈论您所在的目录而不是Python目录.
要做到这一点,你改变这个:
from application.app.folder.file import func_name
对此:
from .application.app.folder.file import func_name
Run Code Online (Sandbox Code Playgroud)
通过添加点,您可以在此文件夹中查找应用程序文件夹,而不是查看Python目录.
dan*_*y74 35
这里的答案缺乏清晰度,这是在Python 3.6上测试的
使用此文件夹结构:
main.py
|
---- myfolder/myfile.py
Run Code Online (Sandbox Code Playgroud)
myfile.py
内容在哪里:
def myfunc():
print('hello')
Run Code Online (Sandbox Code Playgroud)
import语句main.py
是:
from myfolder.myfile import myfunc
myfunc()
Run Code Online (Sandbox Code Playgroud)
这将打印你好.
小智 30
据我所知,__init__.py
直接在要导入的函数的文件夹中添加文件即可完成工作.
dsg*_*g38 20
在linux上的python3中为我工作
import sys
sys.path.append(pathToFolderContainingScripts)
from scriptName import functionName #scriptName without .py extension
Run Code Online (Sandbox Code Playgroud)
Cha*_*anK 19
考虑到application
作为根目录为你的Python项目,创建一个空__init__.py
文件application
,app
和folder
文件夹.然后在some_file.py
make中进行如下更改以获取func_name的定义:
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()
Run Code Online (Sandbox Code Playgroud)
Eri*_*nga 18
我面临同样的挑战,特别是在导入多个文件时,这就是我设法克服它的方法.
import os, sys
from os.path import dirname, join, abspath
sys.path.insert(0, abspath(join(dirname(__file__), '..')))
from root_folder import file_name
Run Code Online (Sandbox Code Playgroud)
wec*_*sam 16
在Python 3.4及更高版本中,您可以直接从源文件导入(链接到文档).
这是一个例子.首先,要导入的文件名为foo.py
:
def announce():
print("Imported!")
Run Code Online (Sandbox Code Playgroud)
导入上述文件的代码受到文档中示例的极大启发:
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()
Run Code Online (Sandbox Code Playgroud)
输出:
<module 'foo' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
Run Code Online (Sandbox Code Playgroud)
请注意,变量名称,模块名称和文件名不能匹配.此代码仍然有效:
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()
Run Code Online (Sandbox Code Playgroud)
输出:
<module 'bar' from '/path/to/foo.py'>
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'announce']
Imported!
Run Code Online (Sandbox Code Playgroud)
在Python 3.1中引入了以编程方式导入模块,使您可以更好地控制模块的导入方式.有关更多信息,请参阅文档.
Zec*_*umo 15
试试Python的相对导入:
from ...app.folder.file import func_name
Run Code Online (Sandbox Code Playgroud)
每个前导点都是从当前目录开始的层次结构中的另一个更高级别.
问题?如果这不适合你,那么你可能会得到许多陷阱的相对进口.阅读答案和评论以获取更多详细信息: 如何修复"非包装中尝试相对导入",即使使用__init__.py也是如此
提示:拥有__init__.py
每个目录级别.您可能需要python -m application.app2.some_folder.some_file
(从.py开始)从顶级目录运行或在PYTHONPATH中拥有该顶级目录.唷!
sch*_*udu 14
就我而言,我有一个要导入的类。我的文件是这样的:
# /opt/path/to/code/log_helper.py
class LogHelper:
# stuff here
Run Code Online (Sandbox Code Playgroud)
在我的主文件中,我通过以下方式包含了代码:
import sys
sys.path.append("/opt/path/to/code/")
from log_helper import LogHelper
Run Code Online (Sandbox Code Playgroud)
Eme*_*eus 13
这适用于Windows
# some_file.py on mainApp/app2
import sys
sys.path.insert(0, sys.path[0]+'\\app2')
import some_file
Run Code Online (Sandbox Code Playgroud)
Nag*_*gev 13
将应用程序移动到其他环境时,使用带有绝对路径的sys.path.append并不理想.使用相对路径并不总是有效,因为当前工作目录取决于脚本的调用方式.
由于应用程序文件夹结构是固定的,我们可以使用os.path来获取我们希望导入的模块的完整路径.例如,如果这是结构:
/home/me/application/app2/some_folder/vanilla.py
/home/me/application/app2/another_folder/mango.py
Run Code Online (Sandbox Code Playgroud)
让我们说你要导入"芒果"模块.您可以在vanilla.py中执行以下操作:
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
Run Code Online (Sandbox Code Playgroud)
当然,您不需要mango_dir变量.
要了解其工作原理,请查看此交互式会话示例:
>>> 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'
>>>
Run Code Online (Sandbox Code Playgroud)
并检查os.path文档.
Moh*_*adi 13
创建包的最佳实践可以是从一个模块(如main_module.py
最高级别的目录)运行和访问其他模块。
此结构演示了您可以通过使用顶级目录文件来使用和访问子包、父包或相同级别的包和模块main_module.py
。
创建并运行这些文件和文件夹进行测试:
package/
|
|----- __init__.py (Empty file)
|------- main_module.py (Contains: import subpackage_1.module_1)
|------- module_0.py (Contains: print('module_0 at parent directory, is imported'))
|
|
|------- subpackage_1/
| |
| |----- __init__.py (Empty file)
| |----- module_1.py (Contains: print('importing other modules from module_1...')
| | import module_0
| | import subpackage_2.module_2
| | import subpackage_1.sub_subpackage_3.module_3)
| |----- photo.png
| |
| |
| |----- sub_subpackage_3/
| |
| |----- __init__.py (Empty file)
| |----- module_3.py (Contains: print('module_3 at sub directory, is imported'))
|
|------- subpackage_2/
| |
| |----- __init__.py (Empty file)
| |----- module_2.py (Contains: print('module_2 at same level directory, is imported'))
Run Code Online (Sandbox Code Playgroud)
现在运行 main_module.py
输出是
>>>'importing other modules from module_1...'
'module_0 at parent directory, is imported'
'module_2 at same level directory, is imported'
'module_3 at sub directory, is imported'
Run Code Online (Sandbox Code Playgroud)
打开图片和文件注意:
在包结构中,如果要访问照片,请使用最高级别目录中的绝对目录。
让我们假设你正在跑步main_module.py
并且你想打开photo.png
inside module_1.py
。
什么module_1.py
必须包含如下:
正确的:
image_path = 'subpackage_1/photo.png'
cv2.imread(image_path)
Run Code Online (Sandbox Code Playgroud)
错误的:
image_path = 'photo.png'
cv2.imread(image_path)
Run Code Online (Sandbox Code Playgroud)
虽然module_1.py
和photo.png
都在同一个目录下。
WY *_*Hsu 11
我多次遇到同样的问题,所以我想分享我的解决方案。
以下解决方案适用于在 Python 3.X 版中开发您的应用程序的人,因为自 Jan/1/2020 以来不支持 Python 2。
在 python 3 中,__init__.py
由于隐式命名空间包,您不需要在您的项目子目录中。见是的init的.py不需要在Python包3.3+
Project
??? main.py
??? .gitignore
|
??? a
| ??? file_a.py
|
??? b
??? file_b.py
Run Code Online (Sandbox Code Playgroud)
在file_b.py
,我想进口类A
中file_a.py
的文件夹下。
无需安装软件包,就像您目前正在开发新项目一样
使用try catch
来检查是否有错误。代码示例:
import sys
try:
# The insertion index should be 1 because index 0 is this file
sys.path.insert(1, '/absolute/path/to/folder/a') # the type of path is string
# because the system path already have the absolute path to folder a
# so it can recognize file_a.py while searching
from file_a import A
except (ModuleNotFoundError, ImportError) as e:
print("{} fileure".format(type(e)))
else:
print("Import succeeded")
Run Code Online (Sandbox Code Playgroud)
一旦你安装了你的应用程序(在这篇文章中,安装教程不包括在内)
你可以简单地
try:
from __future__ import absolute_import
# now it can reach class A of file_a.py in folder a
# by relative import
from ..a.file_a import A
except (ModuleNotFoundError, ImportError) as e:
print("{} fileure".format(type(e)))
else:
print("Import succeeded")
Run Code Online (Sandbox Code Playgroud)
快乐编码!
her*_*rin 10
我很特别:我在Windows上使用Python!
我只是完整的信息:对于Windows和Linux,相对路径和绝对路径都工作sys.path
(我需要相对路径,因为我在几台PC上和不同的主目录下使用我的脚本).
而在使用Windows时都\
和/
可以作为分隔符的文件名,当然你必须加倍\
到Python字符串,
一些有效的例子:
sys.path.append('c:\\tools\\mydir')
sys.path.append('..\\mytools')
sys.path.append('c:/tools/mydir')
sys.path.append('../mytools')
Run Code Online (Sandbox Code Playgroud)
(注意:我认为这/
比\
事件更方便,因为它与Windows兼容,因为它与Linux兼容,并且更易于编写和复制到Windows资源管理器)
以下对我有用:
\n操作系统:Windows 10
\nPython:v3.10.0
\n注意:由于我是Python v3.10.0,所以我没有使用__init__.py
文件,无论如何这对我不起作用。
application\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 app\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 folder\n\xe2\x94\x82 \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 file.py\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 app2\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 some_folder\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 some_file.py\n
Run Code Online (Sandbox Code Playgroud)\nWY Hsu 的第一个解决方案对我有用。为了清楚起见,我重新发布了它并提供了绝对文件参考:
\nimport sys\nsys.path.insert(1, \'C:\\\\Users\\\\<Your Username>\\\\application\')\nimport app2.some_folder.some_file\n\nsome_file.hello_world()\n
Run Code Online (Sandbox Code Playgroud)\n替代解决方案:但是,这也对我有用:
\nimport sys\nsys.path.append( \'.\' )\nimport app2.some_folder.some_file\n\nsome_file.hello_world()\n
Run Code Online (Sandbox Code Playgroud)\n虽然,我不明白为什么它有效。我认为点是对当前目录的引用。但是,当打印当前文件夹的路径时,当前目录已列在顶部:
\nfor path in sys.path:\n print(path)\n
Run Code Online (Sandbox Code Playgroud)\n
如果从特定路径加载模块的目的是在开发自定义模块期间为您提供帮助,则可以在测试脚本的同一文件夹中创建指向自定义模块根目录的符号链接.对于在该文件夹中运行的任何脚本,此模块引用将优先于为同名安装的任何其他模块.
我在Linux上测试了它,但它应该适用于任何支持符号链接的现代操作系统.
这种方法的一个优点是,您可以指向位于您自己的本地SVC分支工作副本中的模块,这可以大大简化开发周期时间并减少管理不同版本模块的故障模式.
小智 7
我的解决方案适用于包中包含所有必需内容__init__.py
但导入仍然不起作用的人。
import sys
import os
sys.path.insert(0, os.getcwd())
import application.app.folder.file as file
Run Code Online (Sandbox Code Playgroud)
我正在开发一个项目a
,我希望用户通过pip install a
以下文件列表进行安装:
.\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 setup.py\n\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 MANIFEST.in\n\xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 a\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 a.py\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 b\n \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py\n \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 b.py\n
Run Code Online (Sandbox Code Playgroud)\n\n安装程序.py
\n\nfrom setuptools import setup\n\nsetup (\n name='a',\n version='0.0.1',\n packages=['a'],\n package_data={\n 'a': ['b/*'],\n },\n)\n
Run Code Online (Sandbox Code Playgroud)\n\n清单文件
\n\nrecursive-include b *.*\n
Run Code Online (Sandbox Code Playgroud)\n\n一个/初始化.py
\n\nfrom __future__ import absolute_import\n\nfrom a.a import cats\nimport a.b\n
Run Code Online (Sandbox Code Playgroud)\n\na/a.py
\n\ncats = 0\n
Run Code Online (Sandbox Code Playgroud)\n\na/b/初始化.py
\n\nfrom __future__ import absolute_import\n\nfrom a.b.b import dogs\n
Run Code Online (Sandbox Code Playgroud)\n\na/b/b.py
\n\ndogs = 1\n
Run Code Online (Sandbox Code Playgroud)\n\n我通过从目录运行以下命令来安装该模块MANIFEST.in
:
python setup.py install\n
Run Code Online (Sandbox Code Playgroud)\n\n然后,从文件系统上完全不同的位置/moustache/armwrestle
我可以运行:
import a\ndir(a)\n
Run Code Online (Sandbox Code Playgroud)\n\n这证实了a.cats
确实等于 0 并且a.b.dogs
确实等于 1,正如预期的那样。
这对我有用。
Python 将包含您启动的脚本的文件夹添加到 PYTHONPATH,因此如果您运行
python application/app2/some_folder/some_file.py
Run Code Online (Sandbox Code Playgroud)
仅将文件夹 application/app2/some_folder 添加到路径(而不是您在其中执行命令的基本目录)。相反,将文件作为模块运行,并在 some_folder 目录中添加 __init__.py 。
python -m application.app2.some_folder.some_file
Run Code Online (Sandbox Code Playgroud)
这会将基目录添加到可执行文件的路径中python
,然后可以通过非相对导入来访问类。
下面的代码以 Python 版本安全的方式导入由其路径给出的 Python 脚本,无论它位于何处:
def import_module_by_path(path):
name = os.path.splitext(os.path.basename(path))[0]
if sys.version_info[0] == 2:
# Python 2
import imp
return imp.load_source(name, path)
elif sys.version_info[:2] <= (3, 4):
# Python 3, version <= 3.4
from importlib.machinery import SourceFileLoader
return SourceFileLoader(name, path).load_module()
else:
# Python 3, after 3.4
import importlib.util
spec = importlib.util.spec_from_file_location(name, path)
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
return mod
Run Code Online (Sandbox Code Playgroud)
我在psutils的代码库中的第 1042 行psutils.test.__init__.py
(截至 2020 年 10 月 9 日的最新提交)中找到了这一点。
使用示例:
script = "/home/username/Documents/some_script.py"
some_module = import_module_by_path(script)
print(some_module.foo())
Run Code Online (Sandbox Code Playgroud)
重要警告:该模块将被视为顶级模块;从其中的父包进行的任何相对导入都将失败。
????root
? ????dir_a
? ? ????file_a.py
? ? ????file_xx.py
? ????dir_b
? ? ????file_b.py
? ? ????file_yy.py
? ????dir_c
? ????dir_n
Run Code Online (Sandbox Code Playgroud)
您可以将父目录添加到PYTHONPATH
,为了实现这一点,您可以使用sys.path
. 因此,您可以轻松添加父目录,如下所示:
# file_b.py
import sys
sys.path.insert(0, '..')
from dir_a.file_a import func_name
Run Code Online (Sandbox Code Playgroud)
小智 5
我在使用 PyCharm 时遇到了同样的问题。我有这个项目结构
skylake\
backend\
apps\
example.py
configuration\
settings.py
frontend\
...some_stuff
Run Code Online (Sandbox Code Playgroud)
和example.pyfrom configuration import settings
中的代码引发了导入错误。
问题是,当我打开 PyCharm 时,它认为skylake是根路径并运行此代码。
sys.path.extend(['D:\\projects\\skylake', 'D:/projects/skylake'])
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,我只是将后端目录标记为源根目录。
它解决了我的问题。
归档时间: |
|
查看次数: |
1208134 次 |
最近记录: |