gevent.monkey --使标准库合作#

实现标准库的协作化。

本模块的主要目的是仔细修补标准库的部分,使其具有与原始库相同的、对gevent友好的功能(至少尽可能接近)。

它的主要接口是 patch_all() 函数,执行所有可用的修补程序。它接受参数来限制对某些模块的修补,但大多数程序 应该 使用默认值,因为它们接收最广泛的测试,并且一些monkey补丁依赖于其他补丁。

修补 应该尽早完成 在程序的生命周期中。例如,主模块 __main__ 或者是第一次导入)应该以该代码开头,最好是在任何其他导入之前:

from gevent import monkey
monkey.patch_all()

上面的推论是修补 应该在主线程上完成should be done while the program is single-threaded .

小技巧

一些框架,如Gunicorn,为您处理猴子修补。检查他们的文档以确定。

警告

太迟的修补可能导致不可靠的行为(例如,一些模块可能仍然使用阻塞套接字)甚至错误。

小技巧

请务必阅读每个补丁功能的文档以检查已知的不兼容性。

查询#

有时,了解对象是否被猴修补是很有帮助的,在高级情况下甚至可以访问原始的标准库函数。本模块为此目的提供功能。

插件和事件#

从GEvent 1.3开始,在猴子修补过程中会发出事件。这些事件首先传递给 gevent.events 订户,然后到 setuptools entry points .

定义了以下事件。它们大致按呼叫的顺序列出 patch_all() 将发射它们。

每个事件类记录相应的设置工具入口点名称。将使用单个参数调用入口点,该参数是发送给订阅服务器的类的同一实例。

您可以订阅事件以监视猴子修补过程并对其进行操作,例如通过提升 gevent.events.DoNotPatch .

您还可以订阅这些事件,以提供超出gevent分发范围的额外补丁,无论是用于额外的标准库模块,还是用于第三方软件包。此修补的建议时间在订阅服务器中 gevent.events.GeventDidPatchBuiltinModulesEvent . 例如,自动修补 psycopg2 使用 psycogreen 当呼叫到 patch_all() 是的,你可以这样写代码:

# mypackage.py
def patch_psycopg(event):
    from psycogreen.gevent import patch_psycopg
    patch_psycopg()

在你 setup.py 您可以这样注册:

from setuptools import setup
setup(
    ...
    entry_points={
        'gevent.plugins.monkey.did_patch_builtins': [
            'psycopg2 = mypackage:patch_psycopg',
        ],
    },
    ...
)

对于更复杂的补丁,gevent提供了一个助手方法,您可以调用该方法用自己模块的属性替换模块的属性。此函数还负责发出适当的事件。

用作模块#

有时运行现有的python脚本或模块是有用的,这些脚本或模块不是在gevent下构建为可识别gevent的。为此,此模块可以作为主模块运行,传递脚本及其参数。有关详细信息,请参见 main() 功能。

在 1.3b1 版本发生变更: 增加了对插件的支持,并开始发出will/did补丁事件。

get_original(mod_name, item_name)[源代码]#

从模块中检索原始对象。

如果对象尚未修补,则仍将检索该对象。

参数:
  • mod_name (str) -- 标准库模块的名称,例如, 'socket' . 也可以是一个标准库模块的序列,提供其他名称供尝试,例如。, ('thread', '_thread') ;第一个可导入模块将提供所有 item_name 项目。

  • item_name -- 一个字符串或字符串序列,用于命名模块上的属性。 mod_name 返回。

返回:

如果为指定了字符串,则返回原始值 item_name 如果传递了序列,则为原始值序列。

is_module_patched(mod_name)[源代码]#

检查模块是否已更换为合作版本。

参数:

mod_name (str) -- 标准库模块的名称,例如, 'socket' .

is_object_patched(mod_name, item_name)[源代码]#

检查模块中的对象是否已替换为合作版本。

参数:
  • mod_name (str) -- 标准库模块的名称,例如, 'socket' .

  • item_name (str) -- 模块中属性的名称,例如, 'create_connection' .

main()[源代码]#

monkey-monkey修补标准模块以使用gevent。

用途: python -m gevent.monkey [MONKEY OPTIONS] [--module] (script|module) [SCRIPT OPTIONS]

如果没有MONKEY选项,MONKEY会像调用 patch_all() . 您可以排除具有--no-<module>的模块,例如--no thread。您可以指定要用--<module>进行修补的模块,例如--socket。在后一种情况下,只修补命令行中指定的模块。

默认行为是执行作为参数传递的脚本。如果要运行模块,请传递 --module 在模块名之前的参数。

在 1.3b1 版本发生变更: 这个 脚本 参数现在可以是任何可以传递给 runpy.run_path, just like the interpreter itself does, for example a package directory containing ``_ _主“y”。以前它必须是.py源文件的路径。

在 1.5 版本发生变更: 这个 --module 已添加选项。

猴子选项: --verbose --[no-]socket, --[no-]dns, --[no-]time, --[no-]select, --[no-]thread, --[no-]os, --[no-]ssl, --[no-]subprocess, --[no-]sys, --[no-]builtins, --[no-]signal, --[no-]queue, --[no-]contextvars

patch_all(socket=True, dns=True, time=True, select=True, thread=True, os=True, ssl=True, subprocess=True, sys=False, aggressive=True, Event=True, builtins=True, signal=True, queue=True, contextvars=True, **kwargs)[源代码]#

执行所有默认的monkey补丁(调用此模块中的其他所有适用函数)。

返回:

如果未取消修补所有模块,则为真值;如果取消修补,则为假值。

在 1.1 版本发生变更: 发行A warning 如果用不同的参数多次调用此函数。第二次和后续调用将只添加更多的修补程序,它们无法通过将参数设置为 False .

在 1.1 版本发生变更: 发行A warning 如果使用 os=Falsesignal=True . 这将导致不调用SIGCHLD处理程序。这可能是将来的错误。

在 1.3a2 版本发生变更: Event 默认为true。

在 1.3b1 版本发生变更: 定义了返回值。

在 1.3b1 版本发生变更: 添加 **kwargs 为了事件订阅者的利益。警告:gevent将来可能会添加和解释其他参数,因此建议使用前缀来解释Kwarg值,例如,插件将其解释为 patch_all(mylib_futures=True) .

在 1.3.5 版本发生变更: 添加 队列 ,默认为true,对于python 3.7。

在 1.5 版本发生变更: 移除 httplib 争论。以前,设置它会引发一个 ValueError .

在 1.5a3 版本发生变更: 添加 contextvars 争论。

在 1.5 版本发生变更: 更好地处理多次修补。

patch_builtins()[源代码]#

制造内置的 __import__() 功能 greenlet safe 在python 2下。

备注

这在Python3下不起作用,因为它是不必要的。python 3的特点是改进了每个模块的导入锁,而不是全局的。

自 23.7.0 版本弃用: 在任何受支持的平台上不执行任何操作。

patch_dns()[源代码]#

替换 DNS functions 在里面 socket 与合作版本。

只有当 patch_socket() 已被调用,并在被请求时由该方法自动完成。

patch_module(target_module, source_module, items=None)[源代码]#

替换中的属性 target_module 在中具有相同名称的属性 source_module .

这个 source_module 可以提供一些属性来定制流程:

  • __implements__ 是要复制的属性名称列表;如果不存在,则 项目 关键字参数是必需的。 __implements__ 必须只包含标准库模块中的名称。

  • _gevent_will_monkey_patch(target_module, items, warn, **kwargs)

  • _gevent_did_monkey_patch(target_module, items, warn, **kwargs) 这两个功能在 source_module 被称为 if 它们分别存在于复制属性之前和之后。“will”功能可以修改 项目 .价值 warn 是一个应使用单个字符串参数调用的函数,以向用户发出警告。如果“will”函数上升 gevent.events.DoNotPatch ,不进行修补。在任何事件订阅服务器或插件之前调用这些函数。

参数:

items (list) -- 要替换的属性名称列表。如果没有给出,将从 source_module __implements__ 属性。

返回:

如果完成了修补,则为真值;如果取消了修补,则为假值。

在 1.3b1 版本加入.

patch_os()[源代码]#

替换 os.fork() 具有 gevent.fork() ,在posix上, os.waitpid() 具有 gevent.os.waitpid() (如果环境变量 GEVENT_NOWAITPID 未定义)。如果叉子不可用,则不执行任何操作。

小心

此方法必须与 patch_signal() 拥有适当的 SIGCHLD 处理,从而纠正 waitpid . patch_all() 默认情况下调用两个。

小心

为了 SIGCHLD 要正确处理,必须运行事件循环。确保这一点的最简单方法是 patch_all() .

patch_queue()[源代码]#

在python 3.7及更高版本上,替换 queue.SimpleQueue (在C中实现)及其对应的Python。

在 1.3.5 版本加入.

patch_select(aggressive=True)[源代码]#

替换 select.select() 具有 gevent.select.select()select.poll() 具有 gevent.select.poll (如有)。

如果 aggressive 为真(默认值),同时从 select .

patch_signal()[源代码]#

使 signal.signal() 函数与 monkey-patched os .

小心

此方法必须与 patch_os() 拥有适当的 SIGCHLD 处理。 patch_all() 默认情况下调用两个。

小心

为了正确 SIGCHLD 处理时,必须屈服于事件循环。使用 patch_all() 这是确保这一点的最简单方法。

参见

gevent.signal

patch_socket(dns=True, aggressive=True)[源代码]#

用gevent的合作套接字替换标准套接字对象。

参数:

dns (bool) -- 如果为真(默认值),也会在 socket . 见 名称解析(DNS) 有关详细信息。

patch_ssl() None[源代码]#

替换 ssl.SSLSocket 对象和套接字包装函数 ssl 与合作版本。

只有当 patch_socket() 已被调用。

patch_subprocess()[源代码]#

替换 subprocess.call()subprocess.check_call()subprocess.check_output()subprocess.Popen 具有 cooperative versions .

备注

在Python3下的Windows上,API支持可能与标准库不完全匹配。

patch_sys(stdin=True, stdout=True, stderr=True)[源代码]#

补丁系统标准 [进,出,呃] 通过线程池使用合作IO。

这是相对危险的,可能会产生意想不到的后果,例如挂起进程或 misinterpreting control keys 什么时候? input()raw_input() 被使用。 patch_all()not 默认情况下调用此函数。

这个方法对python 3没有任何作用。python 3解释器希望在关闭时刷新组成stderr/stdout的textiographer对象,但在关闭时使用threadpool会导致挂起。

自 23.7.0 版本弃用: 在任何支持的版本上不执行任何操作。

patch_thread(threading=True, _threading_local=True, Event=True, logging=True, existing_locks=True) None[源代码]#

替换标准 thread 使其基于greenlet的模块。

参数:
  • threading (bool) -- 当为真(默认值)时,还将修补 threading .

  • _threading_local (bool) -- 当为真(默认值)时,还将修补 _threading_local.local .

  • logging (bool) -- 如果为真(默认值),则在配置了日志记录模块的情况下也会使用补丁锁。

  • existing_locks (bool) -- 如果为true(默认值),并且进程仍然是单线程的,请确保 threading.RLock (在python 3下, importlib._bootstrap._ModuleLock )当前锁定的实例可以正确解锁。 重要的 :这是尽最大努力的尝试,在某些实现中,可能不会检测到所有锁。在启动过程中非常早地进行monkey-patch是很重要的。不建议将其设置为False,尤其是在python2上。

小心

猴子修补 thread 并使用 multiprocessing.Queueconcurrent.futures.ProcessPoolExecutor (使用 Queue )将挂起进程。

在某些平台上,使用此函数和使用子解释器(以及高级C级API)和线程进行Money修补可能会不稳定。

在 1.1b1 版本发生变更: 添加 登录中existing_locks 参数。

在 1.3a2 版本发生变更: Event 默认为true。

patch_time()[源代码]#

替换 time.sleep() 具有 gevent.sleep() .