diff --git a/README.md b/README.md index 25cf389..f212da6 100644 --- a/README.md +++ b/README.md @@ -196,11 +196,30 @@ logging.getLogger('command_runner').setLevel(logging.CRITICAL) Example: ```python from command_runner import command_runner + + exit_code, output = command_runner('ping 127.0.0.1', method='poller') exit_code, output = command_runner('ping 127.0.0.1', method='monitor') ``` -#### Stream redirection +#### stdin stream redirection + +`command_runner` allows to redirect some stream directly into the subprocess it spawns. + +Example code +```python +import sys +from command_runner import command_runner + + +exit_code, output = command_runner("gzip -d", stdin=sys.stdin.buffer) +print("Uncompressed data", output) +``` +The above program, when run with `echo "Hello, World!" | gzip | python myscript.py` will show the uncompressed string `Hello, World!` + +You can use whatever file descriptor you want, basic ones being sys.stdin for text input and sys.stdin.buffer for binary input. + +#### stdout / stderr stream redirection command_runner can redirect stdout and/or stderr streams to different outputs: - subprocess pipes @@ -426,6 +445,7 @@ It also uses the following standard arguments: - timeout (int): seconds before a process tree is killed forcefully, defaults to 3600 - shell (bool): Shall we use the cmd.exe or /usr/bin/env shell for command execution, defaults to False - encoding (str/bool): Which text encoding the command produces, defaults to cp437 under Windows and utf-8 under Linux + - stdin (sys.stdin/int): Optional stdin file descriptor, sent to the process command_runner spawns - stdout (str/queue.Queue/function/False/None): Optional path to filename where to dump stdout, or queue where to write stdout, or callback function which is called when stdout has output - stderr (str/queue.Queue/function/False/None): Optional path to filename where to dump stderr, or queue where to write stderr, or callback function which is called when stderr has output - no_close_queues (bool): Normally, command_runner sends None to stdout / stderr queues when process is finished. This behavior can be disabled allowing to reuse those queues for other functions wrapping command_runner diff --git a/command_runner/__init__.py b/command_runner/__init__.py index 6a5f746..70267b2 100644 --- a/command_runner/__init__.py +++ b/command_runner/__init__.py @@ -19,10 +19,10 @@ __intname__ = "command_runner" __author__ = "Orsiris de Jong" -__copyright__ = "Copyright (C) 2015-2023 Orsiris de Jong for NetInvent SASU" +__copyright__ = "Copyright (C) 2015-2024 Orsiris de Jong for NetInvent SASU" __licence__ = "BSD 3 Clause" -__version__ = "1.5.2" -__build__ = "2023122701" +__version__ = "1.6.0" +__build__ = "2024010401" __compat__ = "python2.7+" import io @@ -462,6 +462,7 @@ def command_runner( timeout=3600, # type: Optional[int] shell=False, # type: bool encoding=None, # type: Optional[Union[str, bool]] + stdin=None, # type: Optional[Union[int, str, Callable, queue.Queue]] stdout=None, # type: Optional[Union[int, str, Callable, queue.Queue]] stderr=None, # type: Optional[Union[int, str, Callable, queue.Queue]] no_close_queues=False, # type: Optional[bool] @@ -910,6 +911,7 @@ def _monitor_process( if sys.version_info >= (3, 6): process = subprocess.Popen( command, + stdin=stdin, stdout=_stdout, stderr=_stderr, shell=shell, @@ -924,6 +926,7 @@ def _monitor_process( else: process = subprocess.Popen( command, + stdin=stdin, stdout=_stdout, stderr=_stderr, shell=shell,