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

1.sys模块之stdout,stderr

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

sys.stdin
sys.stdout
sys.stderr

  File objects corresponding to the interpreter’s standard input, output and error streams. stdin is used for all interpreter
input 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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值