Monkey Patching in python: When we need it?

前端 未结 2 2107
暗喜
暗喜 2021-01-01 06:57

In Python, the term monkey patch only refers to dynamic modifications of a class or module at runtime, As a beginner its really difficult to me understand this

2条回答
  •  无人及你
    2021-01-01 07:15

    Monkey-patching is a way to make some global under-the-hood change in a way that existing code will continue to run, but with modified behavior.

    A really really trivial example of changing the behavior of the builtin str command:

    b.py

    def foo(msg):
        s = str(msg)
        print s, type(s)
    

    a.py

    import b
    
    b.foo('foo')
    
    # monkey-patch 
    import __builtin__
    __builtin__.str = unicode
    
    b.foo('foo')
    
    # Results:
    #foo 
    #foo 
    

    The a module has modified the behavior of other code using the str command, by patching it to use unicode instead. This would be necessary since we pretend that we have no access to b.py's code. It could have been a huge package that we simply use and can't change. But we can slip in new code to be called that changes the behavior.

    A real world example from gevent

    >>> import gevent
    >>> from gevent import socket
    >>> urls = ['www.google.com', 'www.example.com', 'www.python.org']
    >>> jobs = [gevent.spawn(socket.gethostbyname, url) for url in urls]
    >>> gevent.joinall(jobs, timeout=2)
    >>> [job.value for job in jobs]
    ['74.125.79.106', '208.77.188.166', '82.94.164.162']  
    

    The example above used gevent.socket for socket operations. If the standard socket module was used it would took it 3 times longer to complete because the DNS requests would be sequential. Using the standard socket module inside greenlets makes gevent rather pointless, so what about module and packages that are built on top of socket?

    That’s what monkey patching for. The functions in gevent.monkey carefully replace functions and classes in the standard socket module with their cooperative counterparts. That way even the modules that are unaware of gevent can benefit from running in multi-greenlet environment.

    >>> from gevent import monkey; monkey.patch_socket()
    >>> import urllib2 # it's usable from multiple greenlets now
    

提交回复
热议问题