导入kafka的TopicPartition失败引起的对python的import导入机制的学习

本地环境运行python程序时报了一个模块导入错误“ImportError: cannot import name TopicPartition”,但是线上环境没有问题。难道本地没安装第三方kafka的包吗?先看下本地和线上安装的kafka的包的情况:

本地安装了3个版本的kafka包
$ ls /usr/lib/python2.7/site-packages/ka
kafka-1.3.5-py2.7.egg/            kafka_python-0.9.5_dev-py2.7.egg  kafka_python-1.4.3-py2.7.egg/ 

线上环境只有1个版本的kafka包
$ ls /usr/lib/python2.7/site-packages/kafka-1.3.5-py2.7.egg/
EGG-INFO  kafka

由此可以看出并不是本地没有安装kafka包,而是安装了3个包,导入的时候可能导入了和线上不同的版本的kafka,而且这个版本里没有TopicPartition。如何验证这个想法呢 ?可以通过查看包的版本信息来验证:

>>> import kafka
>>> print kafka.__version__
0.9.5-dev

如上,在python交互模式下导入kafka并查看版本,版本是0.9.5-dev并不是线上的1.3.5版本。而且通过查看0.9.5-dev版本的包可以确定这个版本没有TopicPartition。

那么问题来了,导入的第三方包存在多个版本的时候如何决定导入哪个版本呢 ?怎么做才能成功的导入1.3.5版本而不是0.9.5-dev版本呢 ?

一直没考虑过import是怎么找到包并且导入的,借此机会学一下。python按照如下顺序搜索包(网上查的不一定准确):

1. 程序的主目录

2. PYTHONPATH目录,这是一个环境变量设置,linux下可以通过echo $PYTHONPATH查看,默认是空

3. 标准库目录

4. 任何.pth文件的内容

由于包是通过easy_install工具安装的,查看easy-install.pth发现以下内容:

$ cat /usr/lib/python2.7/site-packages/easy-install.pth   
import sys; sys.__plen = len(sys.path)
./xgboost-0.6-py2.7.egg
./redis-2.10.5-py2.7.egg
./protobuf-2.6.1-py2.7.egg
./kafka_python-0.9.5_dev-py2.7.egg      
./kazoo-2.2.1dev-py2.7.egg
./kafka-1.3.5-py2.7.egg    

发现同时存在0.9.5-dev和1.3.5版本,而且0.9.5-dev在前面,是不是由于顺序的原因导入了0.9.5-dev不得而知,现在把0.9.5-dev版本卸载应该就能成功导入1.3.5版本。可如何卸载easy_install安装的包呢?查到这么一个方式,分两步:

1. easy_install-2.7 -m kafka (这个-m参数其实是多版本的意思,并没有卸载的作用)

2. 手动删除egg包

$ sudo easy_install-2.7 -m kafka
Searching for kafka
Best match: kafka 1.3.5
Processing kafka-1.3.5-py2.7.egg
Removing kafka 1.3.5 from easy-install.pth file

Using /usr/lib/python2.7/site-packages/kafka-1.3.5-py2.7.egg
。。。

执行完之后发现好像把1.3.5版本“卸载”了,再卸载下0.9.5-dev版本:

$ sudo easy_install-2.7 -m kafka_python                 
Searching for kafka-python
Best match: kafka-python 1.4.3
Processing kafka_python-1.4.3-py2.7.egg
Removing kafka-python 0.9.5-dev from easy-install.pth file

Using /usr/lib/python2.7/site-packages/kafka_python-1.4.3-py2.7.egg
。。。

看起来0.9.5-dev版本也被“卸载”了,现在看下easy-install.pth文件和包的情况,发现pth里没有kafka包的信息了,多个版本的kafka包还在:

$ cat /usr/lib/python2.7/site-packages/easy-install.pth 
import sys; sys.__plen = len(sys.path)
./xgboost-0.6-py2.7.egg
./redis-2.10.5-py2.7.egg
./protobuf-2.6.1-py2.7.egg
./kazoo-2.2.1dev-py2.7.egg

$ ls /usr/lib/python2.7/site-packages/kafka
kafka-1.3.5-py2.7.egg/            kafka_python-0.9.5_dev-py2.7.egg  kafka_python-1.4.3-py2.7.egg/  

接下来试试导入kafka是什么结果,发现导入失败:

Python 2.7.5 (default, Oct 30 2018, 23:45:53) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import kafka
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named kafka

看来尽管site-packages里有kafka包,但pth文件里没有也会导致导入失败,真是始料未及。

现在把0.9.5-dev版本的包通过rm的方式删除,同时通过easy_install把1.3.5的包安装上应该就可以正常导入了:

删除包文件
$ sudo rm /usr/lib/python2.7/site-packages/kafka_python-0.9.5_dev-py2.7.egg 

安装1.3.5版本
$ sudo easy_install-2.7 kafka==1.3.5
Searching for kafka==1.3.5
Best match: kafka 1.3.5
Processing kafka-1.3.5-py2.7.egg
Adding kafka 1.3.5 to easy-install.pth file

查看easy-install.pth文件发现1.3.5版本在里面了
$ cat /usr/lib/python2.7/site-packages/easy-install.pth 
import sys; sys.__plen = len(sys.path)
./xgboost-0.6-py2.7.egg
./redis-2.10.5-py2.7.egg
./protobuf-2.6.1-py2.7.egg
./kazoo-2.2.1dev-py2.7.egg
./kafka-1.3.5-py2.7.egg

此时导入kafka成功,版本正确,有TopicPartition:
[GCC 4.8.5 20150623 (Red Hat 4.8.5-36)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import kafka
>>> print kafka.version
<module 'kafka.version' from '/usr/lib/python2.7/site-packages/kafka-1.3.5-py2.7.egg/kafka/version.pyc'>
>>> print kafka.TopicPartition
<class 'kafka.structs.TopicPartition'>

至此程序可以正常跑起来了。python的包导入和包管理真复杂,一个简单的问题折腾了大半天。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值