欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

传递参数的技巧

程序员文章站 2022-04-18 14:45:05
...

python灵活的语法和动态机制,给了写代码的太多 奇技淫巧.


有时候需要包装一个函数,然而函数的参数太多,如果一一赋值,就太罗嗦。

可以考虑使用 locals()或者 从 frame里面提取 各种信息 比如 f_locals/f_globals等等

编写 最基本的命令委托:


@task
def sudo_(command, shell=True, pty=True, combine_stderr=None, user=None,
          quiet=False, warn_only=False, 
          stdout=None, stderr=None, group=None,
          timeout=None, shell_escape=None, capture_buffer_size=None):
    return sudo(**locals())

这样就可以利用 locals()搜集的变量,传递给 sudo原来的函数。


sudo库代码是这样写的:

@needs_host
def sudo(command, shell=True, pty=True, combine_stderr=None, user=None,
    quiet=False, warn_only=False, stdout=None, stderr=None, group=None,
    timeout=None, shell_escape=None, capture_buffer_size=None):
    """
    Run a shell command on a remote host, with superuser privileges.

    `sudo` is identical in every way to `run`, except that it will always wrap
    the given ``command`` in a call to the ``sudo`` program to provide
    superuser privileges.

    `sudo` accepts additional ``user`` and ``group`` arguments, which are
    passed to ``sudo`` and allow you to run as some user and/or group other
    than root.  On most systems, the ``sudo`` program can take a string
    username/group or an integer userid/groupid (uid/gid); ``user`` and
    ``group`` may likewise be strings or integers.

    You may set :ref:`env.sudo_user <sudo_user>` at module level or via
    `~fabric.context_managers.settings` if you want multiple ``sudo`` calls to
    have the same ``user`` value. An explicit ``user`` argument will, of
    course, override this global setting.

    Examples::

        sudo("~/install_script.py")
        sudo("mkdir /var/www/new_docroot", user="www-data")
        sudo("ls /home/jdoe", user=1001)
        result = sudo("ls /tmp/")
        with settings(sudo_user='mysql'):
            sudo("whoami") # prints 'mysql'

    .. versionchanged:: 1.0
        See the changed and added notes for `~fabric.operations.run`.

    .. versionchanged:: 1.5
        Now honors :ref:`env.sudo_user <sudo_user>`.

    .. versionadded:: 1.5
        The ``quiet``, ``warn_only``, ``stdout`` and ``stderr`` kwargs.

    .. versionadded:: 1.5
        The return value attributes ``.command`` and ``.real_command``.

    .. versionadded:: 1.7
        The ``shell_escape`` argument.

    .. versionadded:: 1.11
        The ``capture_buffer_size`` argument.
    """
    return _run_command(
        command, shell, pty, combine_stderr, sudo=True,
        user=user if user else env.sudo_user,
        group=group, quiet=quiet, warn_only=warn_only, stdout=stdout,
        stderr=stderr, timeout=timeout, shell_escape=shell_escape,
        capture_buffer_size=capture_buffer_size,
    )

参数一个一个传递,显得稍微罗嗦点了。


1>补充: 如果定义了局部变量,就可以考虑 使用 pop不需要的参数,委托给 原来的函数。

2>对于 *args,**kwargs,就不能使用 这种 技巧了。

这种技巧省了很多代码。


目前我可以在 fabric里面直接导入原始命令:

Cmd:fab --list-format=normal --list

Created on 2017-10-11

@author: [email protected]
@email:  [email protected]
@copyright: Apache License, Version 2.0

Available commands:

    fabric_tasks.get_
    fabric_tasks.local_
    fabric_tasks.open_shell_
    fabric_tasks.prompt_
    fabric_tasks.put_
    fabric_tasks.reboot_
    fabric_tasks.require_
    fabric_tasks.run_
    fabric_tasks.sudo_


Cmd:fab --show=error --timeout=10 --abort-on-prompts --colorize-errors fabric_tasks.run_:command=python /home/kliu/proj/celery_cmd_worker_restart.py
[[email protected]] Executing task 'fabric_tasks.run_'
[[email protected]] run: python /home/kliu/proj/celery_cmd_worker_restart.py
[[email protected]] out: Cmd:celery multi restart w1 --app=celery_proj --autoscale=10,2 --hostname=laok-1.%h -O fair --heartbeat-interval=5 --workdir=/home/kliu/proj --loglevel=info --queues=laok --autoreload --detach --discard --no-color --events
[[email protected]] out: celery multi v3.1.18 (Cipater)
[[email protected]] out: > Stopping nodes...
[[email protected]] out: 	> [email protected]%h: TERM -> 10620
[[email protected]] out: > Waiting for 1 node -> 10620.....
[[email protected]] out: 	> [email protected]%h: OK
[[email protected]] out: > Restarting node [email protected]%h: OK


通过 locals()解决了 一一参数传递问题。

制作了 celery-task的模板工具,可以灵活处理 远程运维问题。