导入Fernet对象与完整cryptography模块的区别及报错原因咨询
导入Fernet对象与完整cryptography模块的差异及报错原因分析
这是个很常见的Python包导入问题,我来帮你理清楚两种方式的差异和报错的根源:
核心差异:Python包的子模块不会自动加载
cryptography是一个大型的Python包,它内部包含了多个子模块(比如fernet、hazmat、x509等)。Python的包机制默认不会在你导入顶层包时,自动加载所有子模块——也就是说:
- 当你执行
import cryptography时,只有顶层的cryptography包被导入,它的子模块(比如fernet)并没有被加载到内存中,自然也无法通过cryptography.fernet访问。 - 而
from cryptography.fernet import Fernet则是直接定位到fernet子模块,并导入其中的Fernet类,这个过程中Python会自动加载fernet子模块,所以你能直接调用Fernet.generate_key()。
报错原因详解
你第一种写法报错module 'cryptography' has no attribute 'fernet',本质是因为:
你只导入了顶层的cryptography包,但它的fernet子模块并没有被显式加载,Python找不到这个属性。就像你打开了一个文件夹(顶层包),但没打开里面的子文件夹(子模块),自然拿不到子文件夹里的文件(Fernet类)。
修正第一种写法的两种方式
如果你坚持想用第一种导入风格,可以通过显式导入子模块来解决:
方式1:直接导入子模块
import cryptography.fernet key = cryptography.fernet.Fernet.generate_key() print(key)
方式2:先导入顶层包,再手动加载子模块
import cryptography import cryptography.fernet # 手动加载fernet子模块 key = cryptography.fernet.Fernet.generate_key() print(key)
哪种方式更推荐?
显然第二种from cryptography.fernet import Fernet更高效:
- 它只加载你需要的
fernet子模块和Fernet类,不会加载整个cryptography包的冗余内容。 - 代码更简洁,调用时不需要写长长的路径,直接用
Fernet.generate_key()即可。
内容的提问来源于stack exchange,提问作者daReagion
相关产品推荐
相关产品推荐

