Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: load_plugins加载时无法使用相对导入 #32

Closed
rmuchan opened this issue Oct 21, 2020 · 8 comments
Closed

Bug: load_plugins加载时无法使用相对导入 #32

rmuchan opened this issue Oct 21, 2020 · 8 comments
Labels
bug Something isn't working good first issue Good for newcomers

Comments

@rmuchan
Copy link
Contributor

rmuchan commented Oct 21, 2020

描述问题:

在插件中使用相对导入时,使用load_plugins加载插件会抛出ImportError错误。

如何复现?

  1. 在插件目录下创建两个py文件
  2. 在一个文件中通过相对路径导入另一个(from . import
  3. 在main中使用load_plugins加载插件目录
  4. 控制台报错:ImportError: attempted relative import with no known parent package

期望的结果

无错误地加载两个插件。

环境信息:

  • OS: macOS
  • Python Version: 3.8
  • Nonebot Version: 2.0.0a3
@rmuchan rmuchan added the bug Something isn't working label Oct 21, 2020
@rmuchan
Copy link
Contributor Author

rmuchan commented Oct 21, 2020

此外,我注意到NB1中load_plugins是通过调用load_plugin实现的,NB2中直接调用了底层的_load。这一变化使我的bot中对load_plugin的挂钩(为了监视自动部署状态)失效了。请问是为什么做出了这个选择呢?

@Lancercmd
Copy link
Contributor

Lancercmd commented Oct 21, 2020

Python 3 以后,当相对目录中没有 __init__.py 时 Python 不会将该目录识别为一个包,因此会返回 no known parent package ,请问这两个 py 文件是否包含了 __init__.py ?

@rmuchan
Copy link
Contributor Author

rmuchan commented Oct 21, 2020

Python 3 以后,当相对目录中没有 init.py 时 Python 不会将该目录识别为一个包,因此会返回 no known parent package ,请问这两个 py 文件是否包含了 init.py ?

添加__init__.py后仍然报错。测试中发现并没有执行__init__.py的内容,那就是说没有加载插件的父包?

@Lancercmd
Copy link
Contributor

Lancercmd commented Oct 21, 2020

Python 3 以后,当相对目录中没有 __init__.py 时 Python 不会将该目录识别为一个包,因此会返回 no known parent package ,请问这两个 py 文件是否包含了 __init__.py ?

添加 __init__.py 后仍然报错。测试中发现并没有执行 __init__.py 的内容,那就是说没有加载插件的父包?

通过 nonebot.load_plugin 加载指定的一个包,py文件或者存在 __init__.py 的文件夹(被 Python3 所承认的一个合法的包)。相应地, nonebot.load_plugins 也要满足这些条件,考虑你当前的情况可能是需要被导入的包已经嵌套在了多层目录内,那该情况对应的其所有父级目录都需要存在 __init__.py (可以根据情况在必要层级的 __init__.py 进行额外的 import

@Lancercmd
Copy link
Contributor

Lancercmd commented Oct 21, 2020

Python 3 以后,当相对目录中没有 init.py 时 Python 不会将该目录识别为一个包,因此会返回 no known parent package ,请问这两个 py 文件是否包含了 init.py ?

添加 init.py 后仍然报错。测试中发现并没有执行 init.py 的内容,那就是说没有加载插件的父包?

通过 nonebot.load_plugin 加载指定的一个包, py 文件 或 存在 init.py 的文件夹(被 Python3 所承认的一个合法的包)。相应地, nonebot.load_plugins 也要满足这些条件,考虑你当前的情况可能是需要被导入的包已经嵌套在了多层目录内,那该情况对应的其所有父级目录都需要存在 init.py (可以根据情况在必要层级的 init.py 进行额外的 import

当目录结构如下所示:

repo/    # 工作目录
    plugins/
        addons/
            management/
                __init__.py
                solver.py
            test.py
        base.py

以上情况通过 nonebot.load_plugins('plugins') 只能导入 base.py ,因为 addons 目录没有 __init__.py 不是一个合法的包。

此例为了在 solver.py 内导入 test.py 需要确保 addons 目录存在 __init__.py 即构成一个合法的包,然后就可以在 solver.py 通过

from plugins.addons import test    # 当然,需要 plugins/ 目录也存在 __init__.py

才能成功导入 test.py,或者按题主的原意,在 solver.py 用过

from .. import test

来成功导入 test.py 。而像题主在最开始所说的

2.在一个文件中通过相对路径导入另一个(from . import)

理论上如果这个包合法并被成功导入,那同目录下自然可以用 from . import xxx 导入另一个 py 文件。

猜测实际情况可能是从多个父级导入,或者这个问题的本身就是 nonebot.load_plugins() 所使用的路径错。

@yanyongyu
Copy link
Member

@rmuchan 既然是插件式的开发,所以我并不推荐在插件间进行import,这可能带来不必要的麻烦,插件间应该尽可能的解耦。

from . import错误

关于这个问题,你可以尝试如下:

目录结构

BotRepo/
	bot/
		plugins/
			a.py
			b.py

解决方案一

a.py 定义 __package__ = "plugins" 然后 from .b import xxx

解决方案二

b.py 中使用 from a import xxx绝对路径import,前提是a插件在b之前被加载!

@yanyongyu
Copy link
Member

此外,我注意到NB1中load_plugins是通过调用load_plugin实现的,NB2中直接调用了底层的_load。这一变化使我的bot中对load_plugin的挂钩(为了监视自动部署状态)失效了。请问是为什么做出了这个选择呢?

由于nb1中load_plugins需要同时提供路径以及import的前缀,nb2中希望仅通过提供路径进行import,使用了pkgutil.iter_modules遍历路径下的所有插件,如果找到替代方案可以改进这一部分

@rmuchan
Copy link
Contributor Author

rmuchan commented Oct 21, 2020

既然是插件式的开发,所以我并不推荐在插件间进行import,这可能带来不必要的麻烦,插件间应该尽可能的解耦。

有道理,我之前的使用方式跟NB的设计有些出入。把文件下移了一层解决了。

@rmuchan rmuchan closed this as completed Oct 21, 2020
@yanyongyu yanyongyu added the good first issue Good for newcomers label Oct 21, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working good first issue Good for newcomers
Development

No branches or pull requests

3 participants