Simpy 3:在没有'with...as:'的情况下使用Resources.Resource.request()/.release()

3 投票
3 回答
2466 浏览
提问于 2025-04-18 06:56

我正在尝试在我正在做的项目中添加SimPy模拟,但对版本3的请求有些困惑。

我能够顺利地使用'with'语句来实现资源的管理,但在我的情况下,我想在不使用'with'语句的情况下请求和释放资源。

然而,我找不到使用SimPy 3的相关示例。我阅读了关于资源的文档和源代码,但还是没能完全搞明白。有人能解释一下如何正确地:

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

谢谢,抱歉打扰了。

PS:我打算使用Resources.resource。

3 个回答

0

这一切都在 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__ 则负责清理工作。

3

使用 with 语句时,当你进入 with 块时,会调用 __enter__ 方法,而当你离开这个块时,会调用 __exit__ 方法。所以当你写

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

实际上是在对一个请求对象调用 __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 的过程中发生什么异常,它都会确保清理代码被执行。而如果用上面的代码,就没有这个保障了。

6

如果你想在没有with块的情况下使用某个资源(而且你知道不会被打断),那么你只需要这样做:

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

撰写回答