What is the pythonic way to wrap multiple functions in the same with operators

I am using the Python library, Fabric , to do some maintenance on the remote server. Fabric automatically prints all responses to remote and local commands, unless you complete the command in pairs using statements. So on the local machine

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

or like this on a remote computer:

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

I write a long and complex task and repeat the repetition of the two with statements over and over. I want to write a function called _mute () to prevent it from repeating. This will allow me to do something like this:

 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) 

I reviewed some solutions and know that "eval" can do this for me. But every page I read about eval suggests that this is almost always a bad idea due to security concerns. I looked at partial ones, but I could not figure out how to make an argument in my _mute function callable. I assume there is a higher level of Python concept here. What is the pythonic way to do this? Thank you for any direction you could provide.

+6
source share
1 answer

The best solution for you would be to create your own context manager; the easiest way would be to use contextlib.contextmanager decorator :

 from contextlib import contextmanager @contextmanager def _mute(): with settings(warn_only='true'): with hide('running', 'stdout', 'stderr', 'warnings'): yield 

Then use _mute as the context manager:

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

This is much more compact and readable than repeating two large lines of the context manager and has the added advantage that you can now run multiple commands in the same context.

Regarding your question; you can easily apply arbitrary arguments to a given function using the *args syntax:

 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') 

See * args and ** kwargs? for more information on tricks of arbitrary arguments *args .

+11
source

Source: https://habr.com/ru/post/924461/


All Articles