将多个函数包含在同一个语句中的pythonic方法是什么?

bry*_*edy 6 python eval with-statement contextmanager fabric

我正在使用Python库Fabric来进行一些远程服务器维护.Fabric会自动输出对远程和本地命令的所有响应,除非您将命令包装在一对语句中.像这样,在本地机器上,

with settings(warn_only='true'):
    with hide('running', 'stdout', 'stderr', 'warnings'):
        output = local("uname -a", True)
Run Code Online (Sandbox Code Playgroud)

或者像这样在远程机器上:

with settings(warn_only='true'):
    with hide('running', 'stdout', 'stderr', 'warnings'):
        output = run("uname -a")
Run Code Online (Sandbox Code Playgroud)

我正在写一个漫长而复杂的任务,并发现自己一遍又一遍地重复这两个.我想编写一个名为_mute()的函数来防止重复.它会让我做这样的事情:

def _mute(fabric_cmd, args):
    with settings(warn_only='true'):
        with hide('running', 'stdout', 'stderr', 'warnings'):
            output = fabric_cmd(args)
    return output

def some_remote_task():
    # Run a remote task silently
    _mute(remote, 'uname -a')

def some_local_task():
    # Run a local task silently
    _mute(local, 'uname -a', True)
Run Code Online (Sandbox Code Playgroud)

我已经研究了一些解决方案并且知道"eval"可以为我做这件事.但是我读到的关于eval的每一页都表明,由于安全问题,这几乎总是一个坏主意.我调查了部分内容,但我无法弄清楚如何在我的_mute函数中调用参数.我猜这里有一个更高级别的Python概念,我在这里缺少.做这个的pythonic方法是什么?感谢您提供的任何方向.

Mar*_*ers 11

更好的解决方案是建立自己的上下文管理器; 到目前为止最简单的方法是使用contextlib.contextmanager装饰器:

from contextlib import contextmanager

@contextmanager
def _mute():
    with settings(warn_only='true'):
        with hide('running', 'stdout', 'stderr', 'warnings'):
            yield
Run Code Online (Sandbox Code Playgroud)

然后_mute用作上下文管理器:

def some_remote_task():
    # Run a remote task silently
    with _mute():
        output = remote("uname -a")
Run Code Online (Sandbox Code Playgroud)

这比必须重新键入两个更大的上下文管理器行更加紧凑和可读,并且具有额外的优势,即现在可以在同一上下文中运行多个命令.

至于你的问题; 您可以使用以下*args语法轻松地将任意参数应用于给定函数:

def _mute(fabric_cmd, *args):
    with settings(warn_only='true'):
        with hide('running', 'stdout', 'stderr', 'warnings'):
            return fabric_cmd(*args)

def some_remote_task():
    # Run a remote task silently
    output = _mute(remote, 'uname -a')
Run Code Online (Sandbox Code Playgroud)

*args和**kwargs?有关*args任意参数列表技巧的更多信息.