1. northisup
  2. gevent


gevent / gevent / monkey.py

The default branch has multiple heads

# Copyright (c) 2009-2012 Denis Bilenko. See LICENSE for details.
"""Make the standard library cooperative.

The functions in this modul ## only works on monkey_patches that involve 'monkey_original'
from :mod:`gevent` package.
To patch an individual module call the corresponding ``patch_*`` function. For example, to patch
socket module only, call :func:`patch_socket`. To patch all default modules, call ``gevent.monkey.patch_all()``.

Monkey can also patch thread and threading to become greenlet-based. So :func:`thread.start_new_thread`
starts a new greenlet instead and :class:`threading.local` becomes a greenlet-local storage.

Monkey patches:

* :mod:`socket` module -- :func:`patch_socket`

  - :class:`socket`
  - :class:`SocketType`
  - :func:`socketpair`
  - :func:`fromfd`
  - :func:`ssl` and :class:`sslerror`
  - :func:`socket.getaddrinfo`
  - :func:`socket.gethostbyname`
  - It is possible to disable dns patching by passing ``dns=False`` to :func:`patch_socket` of :func:`patch_all`
  - If ssl is not available (Python < 2.6 without ``ssl`` and ``PyOpenSSL`` packages installed) then :func:`ssl` is removed from the target :mod:`socket` module.

* :mod:`ssl` module -- :func:`patch_ssl`

  - :class:`SSLSocket`
  - :func:`wrap_socket`
  - :func:`get_server_certificate`
  - :func:`sslwrap_simple`

* :mod:`os` module -- :func:`patch_os`

  - :func:`fork`

* :mod:`time` module -- :func:`patch_time`

  - :func:`time`

* :mod:`select` module -- :func:`patch_select`

  - :func:`select`
  - Removes polling mechanisms that :mod:`gevent.select` does not simulate: poll, epoll, kqueue, kevent

* :mod:`thread` and :mod:`threading` modules -- :func:`patch_thread`

  - Become greenlet-based.
  - :func:`get_ident`
  - :func:`start_new_thread`
  - :class:`LockType`
  - :func:`allocate_lock`
  - :func:`exit`
  - :func:`stack_size`
  - thread-local storage becomes greenlet-local storage

import sys

__all__ = ['patch_all',

def is_module_patched(name):
    # only works on monkey_patches that involve 'monkey_original'
    # i.e. does not work for 'time', 'sleep'
    source = getattr(__import__('gevent.' + name), name)
    target = getattr(source, '__target__', name)
    dest = __import__(target)
    original = getattr(dest, 'monkey_original', None)
    return True if original else False

def are_modules_patched(names=None):
    if not names:
        names = ["socket", "ssl", "thread", ]

    ret = {}
    for name in names:
        ret[name] = is_module_patched(name)

    return ret

def get_unpatched(name, items):
    # QQQ would prefer to avoid importing gevent.xxx module just to get __target__
    # XXX does not work for 'time', 'sleep'
    source = getattr(__import__('gevent.' + name), name)
    target = getattr(source, '__target__', name)
    dest = __import__(target)
    original = getattr(dest, 'monkey_original', dest)
    if isinstance(items, basestring):
        return getattr(original, items)
        results = []
        for item in items:
            results.append(getattr(original, item))
        return results

class original(object):

def patch_module(name, items=None):
    source = getattr(__import__('gevent.' + name), name)
    target = getattr(source, '__target__', name)
    dest = __import__(target)
    monkey_original = dest.monkey_original = original()
    count = 0
    if items is None:
        items = getattr(source, '__implements__', None)
        if items is None:
            raise AttributeError('%r does not have __implements__' % source)
    for attr in items:
        olditem = getattr(dest, attr, None)
        newitem = getattr(source, attr)
        if olditem is not newitem:
            setattr(monkey_original, attr, olditem)
            setattr(dest, attr, newitem)
            count += 1
    return count

def patch_os():
    """Replace :func:`os.fork` with :func:`gevent.fork`."""
        from gevent.hub import fork
    except ImportError:
    import os
    os.fork = fork

def patch_time():
    """Replace :func:`time.sleep` with :func:`gevent.sleep`."""
    from gevent.hub import sleep
    _time = __import__('time')
    _time.sleep = sleep

def patch_thread(threading=True, _threading_local=True):
    """Replace the standard :mod:`thread` module to make it greenlet-based.
    If *threading* is true (the default), also patch ``threading.local``.
    If *_threading_local* is true (the default), also patch ``_threading_local.local``.
    if not patch_module('thread'):
    from gevent.local import local
    if threading:
        from gevent import thread as green_thread
        threading = __import__('threading')
        # QQQ Note, that importing threading results in get_hub() call.
        # QQQ Would prefer not to import threading at all if it's not used;
        # QQQ that should be possible with import hooks
        threading.local = local
        threading._start_new_thread = green_thread.start_new_thread
        threading._allocate_lock = green_thread.allocate_lock
        threading.Lock = green_thread.allocate_lock
        threading._get_ident = green_thread.get_ident
        from gevent.hub import sleep
        threading._sleep = sleep
    if _threading_local:
        _threading_local = __import__('_threading_local')
        _threading_local.local = local

def patch_socket(dns=True, aggressive=True):
    """Replace the standard socket object with gevent's cooperative sockets.

    If *dns* is true, also patch dns functions in :mod:`socket`.
    from gevent import socket
    # Note: although it seems like it's not strictly necessary to monkey patch 'create_connection',
    # it's better to do it. If 'create_connection' was not monkey patched, but the rest of socket module
    # was, create_connection would still use "green" getaddrinfo and "green" socket.
    # However, because gevent.socket.socket.connect is a Python function, the exception raised by it causes
    # _socket object to be referenced by the frame, thus causing the next invocation of bind(source_address) to fail.
    if dns:
        items = socket.__implements__
        items = set(socket.__implements__) - set(socket.__dns__)
    patch_module('socket', items=items)
    if aggressive:
        if 'ssl' not in socket.__implements__:
            socket.__dict__.pop('ssl', None)

def patch_dns():
    from gevent import socket
    patch_module('socket', items=socket.__dns__)

def patch_ssl():

def patch_select(aggressive=False):
    """Replace :func:`select.select` with :func:`gevent.select.select`.

    If aggressive is true (the default), also remove other blocking functions the :mod:`select`.
    if aggressive:
        select = __import__('select')
        # since these are blocking we're removing them here. This makes some other
        # modules (e.g. asyncore)  non-blocking, as they use select that we provide
        # when none of these are available.
        select.__dict__.pop('poll', None)
        select.__dict__.pop('epoll', None)
        select.__dict__.pop('kqueue', None)
        select.__dict__.pop('kevent', None)

def patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True, httplib=False, aggressive=True):
    """Do all of the default monkey patching (calls every other function in this module."""
    # order is important
    if os:
    if time:
    if thread:
    if socket:
        patch_socket(dns=dns, aggressive=aggressive)
    if select:
    if ssl:
        except ImportError:
            if sys.version_info[:2] > (2, 5):
            # in Python 2.5, 'ssl' is a standalone package not included in stdlib
    if httplib:
        raise ValueError('gevent.httplib is no longer provided, httplib must be False')

if __name__ == '__main__':
    modules = [x.replace('patch_', '') for x in globals().keys() if x.startswith('patch_') and x != 'patch_all']
    script_help = """gevent.monkey - monkey patch the standard modules to use gevent.

USAGE: python -m gevent.monkey [MONKEY OPTIONS] script [SCRIPT OPTIONS]

If no OPTIONS present, monkey patches all the modules it can patch.
You can exclude a module with --no-module, e.g. --no-thread. You can
specify a module to patch with --module, e.g. --socket. In the latter
case only the modules specified on the command line will be patched.

MONKEY OPTIONS: --verbose %s""" % ', '.join('--[no-]%s' % m for m in modules)
    args = {}
    argv = sys.argv[1:]
    verbose = False
    while argv and argv[0].startswith('--'):
        option = argv[0][2:]
        if option == 'verbose':
            verbose = True
        elif option.startswith('no-') and option.replace('no-', '') in modules:
            args[option[3:]] = False
        elif option not in modules:
            args[option] = True
            sys.exit(script_help + '\n\n' + 'Cannot patch %r' % option)
        del argv[0]
        # TODO: break on --
    if verbose:
        import pprint
        import os
        print ('gevent.monkey.patch_all(%s)' % ', '.join('%s=%s' % item for item in args.items()))
        print ('sys.version=%s' % (sys.version.strip().replace('\n', ' '), ))
        print ('sys.path=%s' % pprint.pformat(sys.path))
        print ('sys.modules=%s' % pprint.pformat(sorted(sys.modules.keys())))
        print ('cwd=%s' % os.getcwd())

    if argv:
        sys.argv = argv
        __package__ = None
        print (script_help)