【问题标题】:Simpy 3: Resources.Resource.request()/.release() WITHOUT 'with...as:'简单 3:Resources.Resource.request()/.release() 没有'with...as:'
【发布时间】:2014-07-06 19:25:04
【问题描述】:

我正在尝试将 SimPy 模拟添加到我正在处理的项目中,但我对版本 3 的发布/请求有些困惑。

我能够使用“with”块毫无问题地实现资源,但在我的情况下,我想在不使用“with”块的情况下请求/释放资源。

但是,我找不到使用 SimPy 3 的示例。我阅读了有关资源的文档/源,但仍然不能完全正确。有人可以解释一下如何正确:

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

谢谢,打扰了。

PS:我打算使用 Resources.resource

【问题讨论】:

  • 只需阅读“with”的实际作用。它只是调用对象的例程(我认为是__enter__ 和__close__,但不记得了)。然后做类似的事情。为什么你不想使用“with...As...”呢?

标签: python simulation simpy


【解决方案1】:

如果你想使用没有with 块的资源(并且你知道你不会被打断),它只是:

req = resource.request()
yield req
# do stuff
resource.release(req)

【讨论】:

  • 正是我要问的。我对 Python 生成器的缺乏经验使得学习 SimPy 比原本应该的更难。感谢您开发 SimPy!
  • 如果我有多个资源想要在每个时间单位后“清除”,该怎么办?也许我没有以正确的方式制定这个,但我希望我的进程消耗 2 个单位的资源,所以我做了两次req = resource.request()。但是,当我执行resource.release(req) 时,无论我调用多少次,根据resource.count,这1 个资源仍然在使用中
【解决方案2】:

在对象上使用with 会在您进入with 块时调用__enter__,在您离开时调用__exit__。所以当你这样做时

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

您实际上是在 Request 对象上调用 __enter__,然后调用 #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 期间抛出什么异常,都会调用清理代码。使用上面的代码你会失去它。

【讨论】:

  • 您可以使用try:...finally: 取回清理代码,但也可以使用with...
  • 谢谢,我根据阅读您的帖子编写了这个示例(基于 SimPy 网站文档):gist.github.com/ndmacdon/…
【解决方案3】:

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__ 进行所有清理。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-07-22
    • 2014-12-08
    • 2020-04-05
    • 2010-10-26
    • 1970-01-01
    • 1970-01-01
    • 2019-09-24
    • 2011-09-27
    相关资源
    最近更新 更多