1

假设我有一个 python 方法可以在 p4 中获取最后同步的更改列表。(问题本身与p4无关,只是一个基本的python问题)

def get_last_synced_changelist(p4port, client_name, p4 = None):
    with P4Connection(p4port) as p4:
        last_change_list = p4.run_changes("-m1", "@%s" % client_name)
        if last_change_list:
            return last_change_list[0]["change"]
        else:
            return None

此方法的调用者可以提供作为字符串的 p4port,也可以提供 p4 对象本身。我的要求是,如果提供了“p4”对象,我想在没有上下文的情况下运行方法主体即,我不希望在 p4 上调用enterexit方法。这是因为关闭/进入 p4 对象的责任现在在于调用者。如果未提供 p4 对象,则需要在此程序中使用 p4port 字符串构造 with 语法。

有人能告诉我构建这种方法的最佳方法是什么吗?我想尽可能少地改变身体。基本上像

p4 or with P4Connection(p4port) as p4:
   p4.run_changes(...)

但我不确定最好的语法是什么。

4

3 回答 3

2

这不是直接可能的,with是复合语句,不能嵌入到这样的表达式中。但是您可以利用您的函数还支持“借用”资源的事实:

def get_last_synced_changelist(p4port, client_name, p4 = None):
    if p4 is None:
        with P4Connection(p4port) as p4:
            return get_last_synced_changelist(p4port, client_name, p4)
    last_change_list = p4.run_changes("-m1", "@%s" % client_name)
    if last_change_list:
        return last_change_list[0]["change"]
    else:
        return None

如果您对两个路径有单独的函数,这种方法甚至可以工作(这在本示例中可能有意义,因为在传入p4port现有路径时显然不使用P4Connection)。

于 2013-08-05T12:35:58.917 回答
2

您可以创建一个虚拟上下文管理器:

import contextlib
@contextlib.contextmanager
def dummyctx(x):
    yield x

def get_last_synced_changelist(p4port, client_name, p4=None):
    if p4 is None:
        ctx = P4Connection(p4port)
    else:
        ctx = dummyctx(p4)
    with ctx as p4:
        last_change_list = p4.run_changes("-m1", "@%s" % client_name)
        if last_change_list:
            return last_change_list[0]["change"]
        else:
            return None
于 2013-08-05T12:40:07.757 回答
0

In Python 2 you'll probably want to create your own context manager, either a dummy one as @glglgl shows in his answer, or perhaps one that wraps up the optional creation of the P4Connection:

import contextlib

@contextlib.context_manager
def p4_context(p4port, p4=None):
    p4 is None:
        with P4Connection(p4port) as p4:
            yield p4
    else:
        yield p4

def get_last_synced_changelist(p4port, client_name, p4 = None):
    with p4_context(p4port, p4) as p4:
        last_change_list = p4.run_changes("-m1", "@%s" % client_name)
        if last_change_list:
            return last_change_list[0]["change"]
        else:
            return None

If you were using Python 3.3 or later, you could instead use the awesome new contextlib.ExitStack class:

import contextlib

def get_last_synced_changelist(p4port, client_name, p4 = None):
    with contextlib.ExitStack() as stack:
        if p4 is None:
            p4 = stack.enter_context(P4Connection(p4port))

        last_change_list = p4.run_changes("-m1", "@%s" % client_name)
        if last_change_list:
            return last_change_list[0]["change"]
        else:
            return None
于 2013-08-05T13:00:08.397 回答