Платформа : Python 3.5 на rhel6 (64-разрядная версия)
Сценарий : выполнить команду Bash, которая запускает задание. Это задание возвращает несколько строк вывода на стандартный вывод каждые несколько секунд.
Команда : ./run_job --name 'myjob' --config_file ./myconfig.conf
Цель : использование Python ' s subprocess.run()
, я пытаюсь выполнить указанную выше команду и перехватить стандартный вывод процесса, распечатать его на консоли и сохранить в файл. Мне нужно распечатать стандартный вывод, как только он станет доступным (в режиме реального времени).
Что я попробовал : я много раз искал это, и каждое найденное мной решение использовало subprocess.Popen()
, Этот метод несколько работал, но его реализация привела к нарушению логики возврата c, которая у меня есть в настоящее время. Для чтения Python документации , метод subprocess.run()
рекомендуется с Python 3.5, поэтому я иду по этому маршруту.
Мои настройки : На данный момент у меня есть один общий файл с регистрацией и выполнением команды оболочки ниже.
def setup_logging(log_lvl="INFO"):
script_name = path.splitext(path.basename(__file__))[0]
log_path = environ["HOME"] + "/logs/" + script_name + ".log"
logging.basicConfig(
level=getattr(logging, log_lvl.upper()),
format="%(asctime)s: [%(levelname)s] %(message)s",
handlers=[
logging.FileHandler(filename=log_path, mode="w", encoding="utf-8"),
logging.StreamHandler()
]
)
def run_shell(cmd_str, print_stdout=True, fail_msg=""):
logger = logging.getLogger()
result = run(cmd_str, universal_newlines=True, shell=True, stderr=STDOUT, stdout=PIPE)
cmd_stdout = result.stdout.strip()
cmd_code = result.returncode
if print_stdout and cmd_stdout != "":
logger.info("[OUT] " + cmd_stdout)
if cmd_code != 0 and fail_msg != "":
logger.error(fail_msg)
exit(cmd_code)
return cmd_code, cmd_stdout
Поэтому я бы использовал следующий код для запуска моего скрипта:
run_shell("./run_job --name 'myjob' --config_file ./myconfig.conf", fail_msg="Job failed.")
Это частично работает, но полный стандартный вывод печатается только после завершения процесса. Таким образом, терминал будет зависать, пока это не произойдет. Мне нужно печатать stdout построчно, в режиме реального времени, чтобы он мог быть записан регистратором.
Есть ли способ сделать это, не меняя существующий код? Любая помощь будет оценена.