Tuesday, November 17, 2009

看pydevd.py代码时碰到的问题

代码:
            #pretend pydevd is not the main module, and
            #convince the file to be debugged that it was loaded as main

            sys.modules['pydevd'] = sys.modules['__main__']
            sys.modules['pydevd'].__name__ = 'pydevd'            
            
            from imp import new_module
            m = new_module('__main__')
            sys.modules['__main__'] = m
            m.__file__ = file
            globals = m.__dict__

从这段代码中, 看到sys.modules和imp, 还有'__main__'

说白了, 不明白是什么意思!!!

上次学习, 本人知道每个文件(module)都为一个scope, global对是对于module的. module常常会有三个变量:
0. __package__ : 如果是import一个package的话, 这个变量就是包的名, 如果是module则为None
1. __name__ : 就是import时的名字, package时为包名, module则为模块名. 如果是__main__是指被python载入的文件(module)
2. __file__ : 不是每个import的对象都被这个变量的, 比如上面的imp包就没有, 还有就是直接运行 python 也是没有, 猜测: imp是不是py文件, 可以import入是因为它为python解释器内部的. 一些文档是这样写的: The __file__ attribute is not present for C modules that are
statically linked into the interpreter

虽然常用sys, 还还真少理会sys.module, 文档的解释:

modules
This is a dictionary that maps module names to modules which have already been loaded. This can be manipulated to force reloading of modules and other tricks. Note that removing a module from this dictionary is not the same as calling reload() on the corresponding module object.
看了其实也不是很明白. 只知道是Import入的包. 运行ptyhon(不是ipython):
>>> import sys, pprint
>>> pprint.pprint(sys.modules)
会发现有很多包不是自己import入的.

这个是python进程共import入的包, 已经不是具体某个包的scope了范围, 这种做法的意义: 让module对象可以被相互引用, 因为python进程存在这个变量都是存在的(当然需要import sys)

好了, 再回到最上面的代码, sys.modules['__main__']的含义:

jessinio@niolaptop ~/workspace/python script/src $ python
Python 2.6.2 (r262:71600, Oct 11 2009, 05:51:18)
[GCC 4.3.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> dir()
['__builtins__', '__doc__', '__name__', '__package__']
>>> print __name__
__main__
>>> import sys
>>> dir(sys.modules['__main__'])
['__builtins__', '__doc__', '__name__', '__package__', 'sys']
>>> print sys.modules['__main__'].__name__
__main__


明显是指python首个载入的文件, 因为每个py文件都是一个module, 所以就在这里出现了.

   sys.modules['pydevd'] = sys.modules['__main__']
   sys.modules['pydevd'].__name__ = 'pydevd'   
sys.modules['pydevd']和sys.modules['__main__']都是首个载入的文件(module)的引用 , 然后把首个载入的module scope内的__name__修改了. 这个__name__只是module内的变量

  from imp import new_module
  m = new_module('__main__')
  sys.modules['__main__'] = m
  m.__file__ = file
  globals = m.__dict__
使用API创建一个module对象(-_-!  还有这种玩法的! ) , 然后对外宣传为个新创建的module对象是首个载入的module. -_-! 算不算骗人? 不过还算好心, 还是给出了首个载入的module的路径(就是那个file变量)

了解后, 才明白最上面那段代码的commet是什么意思: 就是自己修改__main__防止被别人修改! 牛!!

下面是new_module的玩法:
>>> import imp
>>> a = imp.new_module('fuck')
>>> type(a)
<type 'module'>
>>> a.__name__
'fuck'

在我眼内, python里"_"开始的变量名都是淫技的开端! ( 不过还没, 淫技没有perl 淫, perl淫是那个乱! ), 淫技学少了会郁闷, 学多了又伤身, 只能适量!

下面学学__dict__这招. 提到__dict__就会扯到:
1. __solts__ : 限制__dict__的内容
2. __get__ : descriptor概念中使用的
3. __getattr__ : 老式的属性获取方法
4. __getattribute__ : 新式的属性获取方法
全是下划线!!

__dict__返回的符号首先与dir函数返回的符号的区别:
看dir()的说明:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.
对于class和instane是有一个递归过程的, 抄祖宗十八代方式的.

>>> class C(object):
...     name = 'class'
...
>>> o = C()
>>> o.__dict__
{}
>>> o.name = 'instance name'
>>> o.__dict__
{'name': 'instance name'}

__dict__ 就是指self指的object自己的属性. 在python里, module, 每层class, instance的namespace就是__dict__
* 相关文档: http://pyref.infogami.com/__dict__

在最上面的代码中, 最后一句就容易理解了: globals = m.__dict__ 就是取得m对象的namespace全部变量, 它被应用于:
        if not IS_PY3K:
            execfile(file, globals, locals) #execute the script
        else:
            #We need to compile before so that the module name is correct
            obj = compile(open(file).read(), file, 'exec')
            exec(obj, globals, locals) #execute the script

当前运行模块(首个被载入的py文件)的CPU时间给了obj 对象使用. 偷吃也要擦嘴就顺便把namespace处理一把

关于在python进程都起作用的淫技应该被称为: Runtime service, 如下URL:
http://docs.python.org/library/python.html

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.