Simpy 3: Resources.Resource.request()/.release() БЕЗ 'withas:'

Я пытаюсь добавить симуляцию SimPy в проект, над которым я работаю, и у меня есть некоторая путаница по поводу выпуска/запроса версии 3.

Я смог без проблем реализовать ресурсы с помощью блока with, но в моей ситуации я хочу запросить/освободить ресурс без использования блока with.

Однако я не могу найти пример этого с использованием SimPy 3. Я прочитал документацию/источник относительно ресурсов, но все еще не могу понять это правильно. Может кто-нибудь объяснить, как правильно:

...
Request a Resource with the method: 'request()'
...
Release that Resource with the method: 'release()'
...

Спасибо, и извините за беспокойство.

PS: я собираюсь использовать Resources.resource


person Cactusman    schedule 18.05.2014    source источник
comment
Просто прочитайте, что with на самом деле делает. Он просто вызывает подпрограммы объекта (думаю, __enter__ и __close__, но не могу вспомнить). А потом сделать что-то подобное. Почему вы не хотите использовать с... как... хотя?   -  person will    schedule 19.05.2014


Ответы (3)


Если вы хотите использовать ресурс без блока with (и вы знаете, что вас не прервут), это просто:

req = resource.request()
yield req
# do stuff
resource.release(req)
person Stefan Scherfke    schedule 19.05.2014
comment
Именно то, что я спрашивал. Моя неопытность в работе с Python-генераторами усложнила изучение SimPy. Спасибо за разработку SimPy! - person Cactusman; 21.05.2014
comment
Что делать, если у меня есть несколько ресурсов, которые я хотел бы очищать после каждой единицы времени? Может быть, я не так формулирую это, но я хотел бы, чтобы мой процесс потреблял 2 единицы ресурса, поэтому я сделал req = resource.request() дважды. Однако, когда я делаю resource.release(req), независимо от того, сколько раз я вызываю этот 1 ресурс, он все равно остается в использовании в соответствии с resource.count - person windyvation; 06.08.2021

Использование with для объекта вызывает __enter__ при входе в блок with и __exit__ при выходе. Итак, когда вы делаете

res = resource.Resource()
with res.request() as req:
  # stuff

Вы действительно вызываете __enter__ для объекта Request, выполняете #stuff, а затем вызываете __exit__:

class Request(base.Put):
    def __exit__(self, exc_type, value, traceback):
        super(Request, self).__exit__(exc_type, value, traceback)
        self.resource.release(self)

class Put(Event):  # base.Put
    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        # If the request has been interrupted, remove it from the queue:
        if not self.triggered:
            self.resource.put_queue.remove(self)

Итак, блок with эквивалентен этому:

res = resource.Resource(...)
req = res.request()
#stuff
if not req.triggered:
   res.put_queue.remove(req)
   res.release(req)

Однако блок with также следит за тем, чтобы код очистки вызывался независимо от того, какие исключения возникают во время #stuff. Вы потеряете это с помощью приведенного выше кода.

person dano    schedule 18.05.2014
comment
Вы возвращаете код очистки, используя try:...finally:, но тогда он может просто использовать with... - person will; 19.05.2014
comment
Спасибо, я закодировал этот пример (на основе документа веб-сайта SimPy) на основе вашего сообщения: gist.github.com/ndmacdon/ - person Cactusman; 19.05.2014

Все это описано в PEP343;

with EXPR as VAR:
        BLOCK

становится:

mgr = (EXPR)
exit = type(mgr).__exit__  # Not calling it yet
value = type(mgr).__enter__(mgr)
exc = True
try:
    try:
        VAR = value  # Only if "as VAR" is present
        BLOCK
    except:
        # The exceptional case is handled here
        exc = False
        if not exit(mgr, *sys.exc_info()):
            raise
        # The exception is swallowed if exit() returns true
finally:
    # The normal and non-local-goto cases are handled here
    if exc:
        exit(mgr, None, None, None)

Это точно то, как python использует блоки with... as..., но я предполагаю, что есть какая-то причина, по которой вы не хотите их использовать. Если это так, то вам просто нужны функции __enter__ и __exit__. Я думаю об этом так: __enter__ все устанавливает, а __exit__ выполняет всю очистку.

person will    schedule 18.05.2014