好得很程序员自学网

<tfoot draggable='sEl'></tfoot>

python模块查找机制探究

python模块查找机制探究

先上段上代码:

 [  root@localhost   ~]  # vi SocketServer.py  

import SocketServer

class MyTCPHandler ( SocketServer . BaseRequestHandler ):

    def handle ( self ):
        self . data = self . request . recv ( 1024 ). strip ()
        print "{} wrote:" . format ( self . client_address [ 0 ])
        print self . data
        self . request . sendall ( self . data . upper ())

if __name__ == "__main__" :
    HOST , PORT = "localhost" , 9999
    server = SocketServer . TCPServer (( HOST , PORT ), MyTCPHandler )
    server . serve_forever ()

这段程序语法上是正确的,但就是运行时报如下的错:

 [  root@localhost   ~]  # python SocketServer.py  
Traceback ( most recent call last ):
  File "SocketServer.py" , line 1 , in <module>
    ? import SocketServer
  File "/root/SocketServer.py" , line 3 , in <module>
    class MyTCPHandler ( SocketServer . BaseRequestHandler ):
AttributeError : 'module' object has no attribute 'BaseRequestHandler'

这个问题是一个刚学python不久的新手遇到的,拿着这个报错信息在网上搜也找不到答案,原因是什么呢?我想大家看到上面我贴出代码就知道是啥原因了,因为这个脚本的名字为SocketServer.py,而在这个脚本中import了SocketServer这个模块,python把当前目录下的SocketServer.py当成了SocketServer模块,解决方法很简单,把脚本的文件名改一下就可以了,这个问题解决,接下来看一下python加载模块的机制,用strace来跟一下这个程序

 stat  (  "/root"  ,  {  st_mode  =  S_IFDIR  |  0550  ,   st_size  =  4096  ,  ...})  =  0  
stat ( "/root" , { st_mode = S_IFDIR | 0550 , st_size = 4096 , ...}) = 0
stat ( "/root/SocketServer" , 0x7fffc5280bf0 ) = - 1 ENOENT ( No such file or directory )
open ( "/root/SocketServer.so" , O_RDONLY ) = - 1 ENOENT ( No such file or directory )
open ( "/root/SocketServermodule.so" , O_RDONLY ) = - 1 ENOENT ( No such file or directory )
open ( "/root/SocketServer.py" , O_RDONLY ) = 3
fstat ( 3 , { st_mode = S_IFREG | 0644 , st_size = 449 , ...}) = 0
open ( "/root/SocketServer.pyc" , O_RDONLY ) = 4
fstat ( 4 , { st_mode = S_IFREG | 0644 , st_size = 856 , ...}) = 0
mmap ( NULL , 4096 , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , - 1 , 0 ) = 0x7f9ec67dc000
read ( 4 , "\3\363\r\n\353\t\36Pc\0\0\0\0\0\0\0\0\3\0\0\0@\0\0\0sf\0\0\0d\0" ..., 4096 ) = 856
fstat ( 4 , { st_mode = S_IFREG | 0644 , st_size = 856 , ...}) = 0
read ( 4 , "" , 4096 )                       = 0
close ( 4 )                                 = 0
munmap ( 0x7f9ec67dc000 , 4096 )             = 0
close ( 3 )                                 = 0

这段是加载模块的地方,我们可以看到python加载模块时,首先是在当前目录下搜索,先stat SocketServer,看SocketServer这个目录是否存在,然后再搜索SocketServer.so,接着搜SocketServermodule.so,最后搜索SocketServer.py和SocketServer.pyc,直到找到,我们发现另外一个现象就是python已经找到了.py文件了,并且打开了,但还是会继续找.pyc文件,这个地方有点奇怪。接着我们跟一下把名字改掉后的脚本:

 stat  (  "/tmp"  ,  {  st_mode  =  S_IFDIR  |  S_ISVTX  |  0777  ,   st_size  =  12288  ,  ...})  =  0  
stat ( "/tmp" , { st_mode = S_IFDIR | S_ISVTX | 0777 , st_size = 12288 , ...}) = 0
stat ( "/tmp/SocketServer" , 0x7fff13219a70 ) = - 1 ENOENT ( No such file or directory )
open ( "/tmp/SocketServer.so" , O_RDONLY )   = - 1 ENOENT ( No such file or directory )
open ( "/tmp/SocketServermodule.so" , O_RDONLY ) = - 1 ENOENT ( No such file or directory )
open ( "/tmp/SocketServer.py" , O_RDONLY )   = - 1 ENOENT ( No such file or directory )
open ( "/tmp/SocketServer.pyc" , O_RDONLY ) = - 1 ENOENT ( No such file or directory )
stat ( "/usr/lib64/python2.6/SocketServer" , 0x7fff13219a70 ) = - 1 ENOENT ( No such file or directory )
open ( "/usr/lib64/python2.6/SocketServer.so" , O_RDONLY ) = - 1 ENOENT ( No such file or directory )
open ( "/usr/lib64/python2.6/SocketServermodule.so" , O_RDONLY ) = - 1 ENOENT ( No such file or directory )
open ( "/usr/lib64/python2.6/SocketServer.py" , O_RDONLY ) = 3
fstat ( 3 , { st_mode = S_IFREG | 0644 , st_size = 21914 , ...}) = 0
open ( "/usr/lib64/python2.6/SocketServer.pyc" , O_RDONLY ) = 4
fstat ( 4 , { st_mode = S_IFREG | 0644 , st_size = 21222 , ...}) = 0
mmap ( NULL , 4096 , PROT_READ | PROT_WRITE , MAP_PRIVATE | MAP_ANONYMOUS , - 1 , 0 ) = 0x2b268d545000
read ( 4 , "m\362\r\nz\17\305Lc\0\0\0\0\0\0\0\0\v\0\0\0@\0\0\0s.\2\0\0d\0" ..., 4096 ) = 4096
close ( 4 )                                 = 0
munmap ( 0x2b268d545000 , 4096 )             = 0

这个看的更加明白了,python会在当前目录下找,然后接着到系统的路径的路径下去找,也就是sys.path

 >>>  import   sys
>>> sys . path
[ '' , '/usr/lib64/python26.zip' , '/usr/lib64/python2.6' , '/usr/lib64/python2.6/plat-linux2' , '/usr/lib64/python2.6/lib-tk' , '/usr/lib64/python2.6/lib-old' , '/usr/lib64/python2.6/lib-dynload' , '/usr/lib64/python2.6/site-packages' ]

我们只要把python模块放在这个sys.path里所在路径下,python就可以找到我们的模块,如果我们python模块不在当前路径下也不在sys.path里怎么办呢?我们有两种方式:

第一种,设置PYTHONPATH:

 假如我将模块放在/  home  /  admin  /下,在终端下执行如下命令:  
$ export PYTHONPATH = $PYTHONPATH : /home/ admin /
$ echo $PYTHONPATH
: /home/ admin /
>>> sys . path
[ '' , '/tmp' , ' /home/admin ' , '/usr/lib64/python26.zip' , '/usr/lib64/python2.6' , '/usr/lib64/python2.6/plat-linux2' , '/usr/lib64/python2.6/lib-tk' , '/usr/lib64/python2.6/lib-old' , '/usr/lib64/python2.6/lib-dynload' , '/usr/lib64/python2.6/site-packages' ]

第二种,在程序运行时修改sys.path就可以

 >>>  import   sys
>>> sys . path
[ '' , '/usr/lib64/python26.zip' , '/usr/lib64/python2.6' , '/usr/lib64/python2.6/plat-linux2' , '/usr/lib64/python2.6/lib-tk' , '/usr/lib64/python2.6/lib-old' , '/usr/lib64/python2.6/lib-dynload' , '/usr/lib64/python2.6/site-packages' ]
>>> sys . path . append ( "/home/admin" )
>>> sys . path
[ '' , '/usr/lib64/python26.zip' , '/usr/lib64/python2.6' , '/usr/lib64/python2.6/plat-linux2' , '/usr/lib64/python2.6/lib-tk' , '/usr/lib64/python2.6/lib-old' , '/usr/lib64/python2.6/lib-dynload' , '/usr/lib64/python2.6/site-packages' , ' /home/admin ' ]

看完了python的模块查找机制后,总感觉这个查找机制不是很高效,如果模块在sys.path这个list最后一个,那么python要把list中所有路径都遍历一遍,假如sys.path的路径很多,遍历一遍还是需要花一些时间。

 

0 Comments

Tags:  module ,  python .

 

Before you can run VMware, several modules must be compiled and loaded into the running kernel

在ubuntu 12.04上安装vmware workstation 8.02,

在vmware kernel module updater这个窗口上,编译第二步Virtual Network Device 时出现错误

查看Log,有如下报错:

 2012  -  06  -  24T14  :  56  :  24.833  +  08  :  00  |   vthread  -  3  |   I120  :  Your   GCC version  :  4.6  
2012 - 06 - 24T14 : 56 : 24.839 + 08 : 00 | vthread - 3 | I120 : Your GCC version : 4.6
2012 - 06 - 24T14 : 56 : 24.855 + 08 : 00 | vthread - 3 | I120 : Header path / lib / modules / 3.2 . 0 - 25 - generic / build / include for kernel release 3.2 . 0 - 25 - generic is valid .
2012 - 06 - 24T14 : 56 : 24.867 + 08 : 00 | vthread - 3 | I120 : Trying to find a suitable PBM set for kernel 3.2 . 0 - 25 - generic .

解决方案:

 # cd /usr/lib/vmware/modules;   
# wget http://pavlinux.ru/vmware/8.0.2/source.tar.lzma;
# tar -xf source.tar.lzma;
# vmware-modconfig --console --install-all

 

3 Comments

Tags:  vmware .

 

http://jasonwu.me/

作者: Leo_wl

    

出处: http://www.cnblogs.com/Leo_wl/

    

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

版权信息

查看更多关于python模块查找机制探究的详细内容...

  阅读:39次