传递参数的技巧
程序员文章站
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的模板工具,可以灵活处理 远程运维问题。