PyCharm中的python_stubs是什么?
我在使用PyCharm时遇到了很多问题,它无法正确识别库中的函数。因此,我决定查看一些示例函数的源代码,这些函数在PyCharm中被错误识别。比如,PyCharm对pickle.load()
的识别就不正确,它认为pickle.load()
没有参数,但实际上它是需要一个参数的。我在这里问过这个问题。于是我写了以下简短的测试代码。
import pickle
r = range(10)
f = open("../temp/pickling_example.pkl", "wb")
pickle.dump(r, f)
f.close()
f = open("../temp/pickling_example.pkl", "rb")
pickle.load(f)
print(r)
我在pickle.load(f)
这行代码上按了Ctrl+B
,希望能跳转到定义pickle.load()
的源文件,但结果却跳到了一个文件,路径是C:\Users\ray\.PyCharm30\system\python_stubs\-1442825926\_pickle.py
。这个文件里包含了以下的抽象内容(见下面的截图)。
在这里,你可以看到PyCharm错误识别pickle.load()
的原因;根据这个文件,pickle.load()
的定义是没有参数的。
有人能解释一下为什么我会被带到这个地方吗?这个文件是什么?还有python_stubs
文件夹(更准确地说是C:\Users\ray\.PyCharm30\system\python_stubs\
)又是什么?
我猜测是这样的。我被带到这个文件是因为PyCharm在我的电脑上找不到pickle.load()
的实际源代码。在这种情况下,PyCharm就会生成一个虚拟文件,里面只有函数的声明(或者说是签名),在这个例子中就是pickle.load()
。我按Ctrl+B
时跳转到的就是这个文件。这个文件的目的是为了让PyCharm的检查功能正常工作,并能提供自动补全,PyCharm把所有这些文件放在python_stubs
目录下。实际上,pickle.load()
函数的定义在我C:\Python34\
目录下的某个pyc
或pyd
文件里,而我没有包含pickle.load()
定义的py
文件,因为我在安装Python时没有安装源代码。
问题:
(1) 我的猜测大致正确吗?能否提供更准确的解释?
(2) 我该如何防止PyCharm错误识别或不识别库函数?我是否应该确保总是安装Python和所有第三方包的源代码,以确保PyCharm能够正常进行检查?
(3) 如果我说的对,PyCharm生成这些文件,那么PyCharm是如何推测函数的签名的?
2 个回答
PEP484 定义了这些 存根文件。根据这个提案,这些文件主要是用来提供类型提示的,可以被类型检查工具使用。
(1) 是的,你说的大部分是对的。
python_stubs
文件是一个自动生成的文件,里面包含了一些内置函数的虚拟定义。这个文件是 PyCharm 用来推测内置函数类型的,特别是在这些函数的类型没有为特定版本写死的时候。
(3) 有时候,仅仅通过文档是无法正确推测内置函数的类型的。有些文档字符串会以“类型签名”开头:
>>> print(min.__doc__)
min(iterable[, key=func]) -> value
min(a, b, c, ...[, key=func]) -> value
但是 pickle.load()
就没有这样的开头。
需要注意的是,这种情况在未来的 Python 版本中可能会改变,因为从 Python 3.4 开始,引入了 Argument Clinic,这使得可以更好地检查用 C 定义的内置函数。我不确定 PyCharm 是否已经能够获取这些信息。
(2) 试着重建 Python 的骨架文件。不过据我所知,如果这样不行,唯一的真正选择就是在 PyCharm 的问题追踪器 上提交一个问题。