порядок исправления обезьяны gevent

На работе мы используем gevent для создания нескольких асинхронных серверов, и есть некоторые споры о том, когда выполнять исправление обезьян по отношению к другим модулям. Документация gevent показывает такие вещи:

from gevent import monkey
monkey.patch_socket()
import socket

Где исправление обезьяны происходит до того, как модули библиотеки были импортированы.

Тем не менее, мой менеджер считает, что порядок исправления обезьян должен быть таким:

import socket
from gevent import monkey
monkey.patch_socket()

Когда исправление обезьяны вызывается после импорта библиотечного модуля. Это выглядит так, как будто обезьяна исправление видит, что модуль сокета был импортирован, и исправляет его в этот момент.

Я нашел несколько дискуссий, в которых говорится, что нужно делать это одним способом, а в других — другим. Мое собственное простое тестирование, кажется, говорит, что это не имеет значения. Есть ли у кого-нибудь мнение по этому поводу с некоторыми четкими причинами или ссылками, в которых говорится, почему?

Заранее спасибо!! Дуг


person writes_on    schedule 16.09.2016    source источник


Ответы (2)


Как текущий сопровождающий gevent, я укажу на документацию, в которой конкретно говорится ( несколько раз), рекомендуемый способ исправления обезьяны — это сделать как можно раньше и желательно до любого другого импорта.

Теперь, с большинством стандартных библиотечных модулей, вы можете обойтись без внесения исправлений после их импорта. Но сторонние библиотеки не обязательно безопасны в этом отношении. В общем, это просто безопаснее и избавляет от проблем с установкой патча как можно скорее.

person Jason Madden    schedule 17.09.2016
comment
Спасибо за удар вверх ногами, я пару раз читал эту документацию и все еще был сбит с толку из-за примеров, которые я видел в сети, которые делают это иначе. Надо было доверять документам. :) - person writes_on; 19.09.2016
comment
Привет, Джейсон. Пожалуйста, объясните, что не так с (Python 3.5.2 в Linux) from gevent.monkey import patch_all; is_module_patched; patch_all(); импортный сокет; is_module_patched(socket) =› False - person dvska; 20.02.2017
comment
is_module_patched(modname) принимает имя модуля, а не сам модуль. - person Jason Madden; 21.02.2017
comment
Документы никогда не оправдывают свою рекомендацию как можно раньше. Они сообщают, только если вы исправите его после X, Y или Z, могут произойти странные вещи. Не могли бы вы рассказать, почему мы должны исправлять как можно раньше, а не до того, как мы сделаем что-либо из X, Y, Z? - person styrofoam fly; 26.03.2018
comment
Есть множество причин, по которым что-то может пойти не так, и гораздо проще сказать, сделайте это заранее, чем перечислять все возможные вещи, которые не должны были произойти до установки патча. В качестве примера: если какой-либо модуль уже сделал «импорт сокета из сокета», к тому времени, когда вы установите патч, все пойдет не так. В общем, вы не можете и не должны знать, выполняет ли модуль «импорт сокета» или «из сокета импорта сокета» в своей внутренней реализации, но только один из них будет работать правильно, если вы исправите его после импорта. - person Jason Madden; 27.03.2018

Что ж, согласно исходному коду (см. ниже) patch_socket вызывает patch_module, который импортирует для вас модуль socket.

def patch_module(name, items=None):
    gevent_module = getattr(__import__('gevent.' + name), name)
    module_name = getattr(gevent_module, '__target__', name)
    module = __import__(module_name)
    if items is None:
        items = getattr(gevent_module, '__implements__', None)
        if items is None:
            raise AttributeError('%r does not have __implements__' % gevent_module)
    for attr in items:
        patch_item(module, attr, getattr(gevent_module, attr))
    return module

См. это в репозитории gevent на GitHub.

Таким образом, вам вообще не нужно импортировать сокет (если, конечно, вы его не используете).

person Laurent LAPORTE    schedule 16.09.2016