在__init__.py中找不到引用'xxx
我在PyCharm里有一个项目,结构是这样的:
-- Sources
|--__init__.py
|--Calculators
|--__init__.py
|--Filters.py
|--Controllers
|--__init__.py
|--FiltersController.py
|--Viewers
|--__init__.py
|--DataVisualization.py
|--Models
|--__init__.py
|--Data
除了在Sources
上面的那个__init__.py
文件,其他的__init__.py
文件都是空的。我收到了很多这样的警告:
在 __init__.py 中找不到引用 'xxx'
比如,我的FiltersController.py
文件里有这么一段代码:
import numpy.random as npr
bootstrap = npr.choice(image_base.data[max(0, x-2):x+3, max(0, y-2):y+3].flatten(), size=(3, 3), replace=True)
然后我就收到了这个警告:
在 __init__.py 中找不到引用 'choice'
我在网上搜索,想知道这是什么意思,以及我该怎么做才能在Python中正确编码。
10 个回答
要解决这个问题,你需要把源文件夹标记为源根目录。虽然不太清楚为什么这样做很重要,但确实是这样。
具体操作步骤如下:
- 右键点击源文件夹
- 选择“标记目录为” --> “源根目录”
- 点击“文件” --> “清除缓存 / 重启...” --> “清除并重启”
我知道这个问题有点老了,但谷歌把我带到这里,所以我想其他人也会像我一样来到这里。
2018年的那个回答是这里被选中的:Pycharm:打开一个正常工作的项目时,IDE里出现“未解决的引用”错误
要注意的是,你只能添加一个 Content Root
,但是可以添加多个 Source Folders
。不需要去碰 __init__.py
文件。
你首先可以看看这个链接。里面解释了当你导入一个包时会发生什么。为了方便理解:
导入语句遵循这样的规则:如果一个包的
__init__.py
文件里定义了一个叫__all__
的列表,那么这个列表就会被当作在使用from package import *
时要导入的模块名称列表。包的作者需要在发布新版本时保持这个列表的更新。如果他们觉得没有必要支持这种导入方式,也可以选择不使用这个列表。
所以PyCharm会尊重这个规则,并显示一个警告信息,这样作者就可以决定在使用*
导入包时,哪些模块会被导入。因此,这似乎是PyCharm的一个有用功能(我认为这绝对不能算是个bug)。你可以通过在__all__
变量中添加要导入的模块名称来轻松去掉这个警告,像这样:
__init__.py
from . import MyModule1, MyModule2, MyModule3
__all__ = [MyModule1, MyModule2, MyModule3]
添加完后,你可以在项目的其他部分按ctrl+click
点击这些模块名称,直接跳转到它们的定义,这个功能我觉得非常实用。
这是一个关于PyCharm的小问题。PyCharm似乎希望你引用的模块里有一个__all__ = []
的声明。
那么,按照编程的好习惯,你应该在模块里加上__all__
声明吗?其实,这就像年轻的斯波克在测试时被问到的问题,他的回答是:“这是值得赞扬的,但不是必须的。”
如果你想绕过这个问题,可以选择全局禁用这个(虽然不太重要但很有用的)检查,或者只针对特定的函数或语句进行抑制。
具体操作步骤:
- 把光标放在出错的文字上(比如你例子中的'choice')
- 打开意图菜单(默认是按alt+enter,我的设置是alt+backspace)
- 按右箭头打开子菜单,选择相关的操作
PyCharm有一些这样的小bug,但我觉得它的优点远远超过缺点。如果你想试试其他好的IDE,还有Spyder/Spyderlib可以选择。
编辑:最开始我以为这个问题只和检查__all__
有关,但看起来它其实是更一般的“未解决引用”检查,这个检查是很有用的。最好还是在语句级别禁用这个功能,可以通过上面提到的菜单,或者在语句前加上# noinspection PyUnresolvedReferences
来实现。