Created
February 13, 2012 01:04
-
-
Save longfin/1812372 to your computer and use it in GitHub Desktop.
eventlet.pathcer.monkey_patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# from eventlet/pathcer.py | |
def monkey_patch(**on): | |
"""Globally patches certain system modules to be greenthread-friendly. | |
The keyword arguments afford some control over which modules are patched. | |
If no keyword arguments are supplied, all possible modules are patched. | |
If keywords are set to True, only the specified modules are patched. E.g., | |
``monkey_patch(socket=True, select=True)`` patches only the select and | |
socket modules. Most arguments patch the single module of the same name | |
(os, time, select). The exceptions are socket, which also patches the ssl | |
module if present; and thread, which patches thread, threading, and Queue. | |
It's safe to call monkey_patch multiple times. | |
""" | |
accepted_args = set(('os', 'select', 'socket', | |
'thread', 'time', 'psycopg', 'MySQLdb')) | |
default_on = on.pop("all",None) | |
for k in on.iterkeys(): | |
if k not in accepted_args: | |
raise TypeError("monkey_patch() got an unexpected "\ | |
"keyword argument %r" % k) | |
if default_on is None: | |
default_on = not (True in on.values()) | |
for modname in accepted_args: | |
if modname == 'MySQLdb': | |
# MySQLdb is only on when explicitly patched for the moment | |
on.setdefault(modname, False) | |
on.setdefault(modname, default_on) | |
modules_to_patch = [] | |
patched_thread = False | |
if on['os'] and not already_patched.get('os'): | |
modules_to_patch += _green_os_modules() | |
already_patched['os'] = True | |
if on['select'] and not already_patched.get('select'): | |
modules_to_patch += _green_select_modules() | |
already_patched['select'] = True | |
if on['socket'] and not already_patched.get('socket'): | |
modules_to_patch += _green_socket_modules() | |
already_patched['socket'] = True | |
if on['thread'] and not already_patched.get('thread'): | |
patched_thread = True | |
modules_to_patch += _green_thread_modules() | |
already_patched['thread'] = True | |
if on['time'] and not already_patched.get('time'): | |
modules_to_patch += _green_time_modules() | |
already_patched['time'] = True | |
if on.get('MySQLdb') and not already_patched.get('MySQLdb'): | |
modules_to_patch += _green_MySQLdb() | |
already_patched['MySQLdb'] = True | |
if on['psycopg'] and not already_patched.get('psycopg'): | |
try: | |
from eventlet.support import psycopg2_patcher | |
psycopg2_patcher.make_psycopg_green() | |
already_patched['psycopg'] = True | |
except ImportError: | |
# note that if we get an importerror from trying to | |
# monkeypatch psycopg, we will continually retry it | |
# whenever monkey_patch is called; this should not be a | |
# performance problem but it allows is_monkey_patched to | |
# tell us whether or not we succeeded | |
pass | |
imp.acquire_lock() | |
try: | |
for name, mod in modules_to_patch: | |
orig_mod = sys.modules.get(name) | |
if orig_mod is None: | |
orig_mod = __import__(name) | |
for attr_name in mod.__patched__: | |
patched_attr = getattr(mod, attr_name, None) | |
if patched_attr is not None: | |
setattr(orig_mod, attr_name, patched_attr) | |
# hacks ahead; this is necessary to prevent a KeyError on program exit | |
if patched_thread: | |
_patch_main_thread(sys.modules['threading']) | |
finally: | |
imp.release_lock() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment