sqlmap源码阅读之基础(dict,sys)

来源:互联网 发布:中科院云计算的股票 编辑:程序博客网 时间:2024/05/20 02:28

1.sys模块之stdout,stderr

    查阅以下python文档可知:任何object及其派生类只要重写了write()方法,均可以替换sys.stdout,sys.stderr.所以

sys.stdinsys.stdoutsys.stderr  File objects corresponding to the interpreter’s standard input, output and error streams. stdin is used for all interpreterinput except for scripts but including calls to input() and raw_input(). stdout is used for the output of print and expression statements and for the prompts of input() and raw_input(). The interpreter’s own prompts and (almost all of) its error messages go to stderr. stdout and stderr needn’t be built-in file objects: any object is acceptable as long as it has a write() method that takes a string argument. 
     基于此,sqlmap作者有以下代码(sqlmap.py中第3部分中):
sys.stdout = StdDbOut(conf.taskid, messagetype="stdout")
     那么此处的StdDbOut又是什么呢?

在lib\utils\api.py中可以看到Class StdDbOut的定义:代码主要就是上面说的那些,重写了write,并赋值替换sys.stdout,sys,stderr。

题外话:

a. write方法中

   def write(self, value, status=CONTENT_STATUS.IN_PROGRESS, content_type=None)
       看看CONTENT_STATUS的定义才发现作者把class当作enum来使了,不太清楚python中的enum
b. write方法中
                if kb.partRun is not None:                    content_type = PART_RUN_CONTENT_TYPES.get(kb.partRun)
       看到kb,挺眼熟的,一翻才发现就是下面的dict的包装类

kb = AttribDict()....class AttribDict(dict):....


2.dict

    之前有在博文中提到sqlmap中用了封装的dict,就是作者自定义一个类型继承自dict.
    阅读作者源代码中不可避免的遇到了原生dict的相关特性,故此,需要参考pydoc

    首先了解下dict,可知其键值必须为hashable,value可以为任意。所谓hashable,参见(https://docs.python.org/2/glossary.html#term-hashable),简单来说呢,就是在生存

    期内,值不能发生变化,与mutable相对。所以,dict的key不能为list,dict,set.具体请参见pydoc.

    至于源码中的self.__dict__()

object.__dict__    A dictionary or other mapping object used to store an object’s (writable) attributes.
self.__class__

instance.__class__    The class to which a class instance belongs.
此处有个小知识点:

        if "_AttribDict__initialised" not in self.__dict__:
这里的_AttribDict__initialised实际是
self.__initialised = True
的变形。具体参见(http://blog.csdn.net/my2010sam/article/details/10949717)
另,此处的self.__getitem__应该是db['xxx']的实现,但是没有找到这个方法的说明,猜的,作者是怎么知道的?

最后再来看看那个深拷贝函数:

    def __deepcopy__(self, memo):        retVal = self.__class__()        memo[id(self)] = retVal        for attr in dir(self):            if not attr.startswith('_'):                value = getattr(self, attr)                if not isinstance(value, (types.BuiltinFunctionType, types.BuiltinFunctionType, types.FunctionType, types.MethodType)):                    setattr(retVal, attr, copy.deepcopy(value, memo))        for key, value in self.items():            retVal.__setitem__(key, copy.deepcopy(value, memo))        return retVal

说白了,是把凡是不能直接拷贝的如对象的id,对象的私有变量,对象中的内建函数和方法属性都特殊处理,其他的都用直接拷贝。

首先是字典整体的属性的处理,后面是字典中每个对象(键值对)的拷贝。

多说一句,那个id就是内存地址。

关于深拷贝参考(http://www.01happy.com/python-shallow-copy-and-deep-copy/)

0 0
原创粉丝点击