반환 코드 및 출력을 기반으로하는 Python 재시도 논리
주어진 재시 도와 지연 횟수로 주어진 명령을 실행하는 함수를 작성하려고합니다. 리턴 코드가 0이고 출력 문자열에 expected_output (partial)이 있으면 루프를 중단하고 리턴 코드와 출력을 리턴해야합니다. 이 코드를 작성하는 것이 더 좋은 것이 있습니까?
cmd check_output_and_retry(cmd, expected_output, delay=1, retry=3):
for i in range(retry):
# Run the given command.
# Return value will be return code with cmd output.
ret, output = execute_cmd(cmd)
if ret == 0 and expected_out in output:
break
else:
time.sleep(delay)
return ret, output
답변
코드 골프의 "이 함수를 작성할 수있는 가장 짧은 방법"을 사용하지 않고 특정 구현에 대한 몇 가지 대안에 주목할 것입니다. 더 간단하다고 생각하는지 고려할 수 있습니다.
if ret == 0와 동일합니다if not ret.if문 에서 더 읽기 쉽지는 않지만 이 변수를 예를 들어program_failed = not ret.expected_out in output출력이 원하는 것인지 평가하기 위해 누군가가 할 수있는 한 가지 일뿐입니다 (예 : 대신 정규식 검사를 원할 수도 있음). 이것을 완전 자유형 함수로 바꾸고 나서 그 함수를 호출하고 그 결과를 사용하고 싶을 수도 있습니다. 예 :if ret == 0 and output_ok(output):이 두 가지를 기반으로 조건을 지정하는 것이 더 예쁘다.
status_ok = ret == 0 output_ok = check_output(output) if status_ok and output_ok: # ...if진술 의 특성상else조건이 불필요합니다. 다음과 같이 작성하는 것과 같습니다.if condition: break time.sleep(delay)당신은
return ret, output여부를 프로그램이 혼동 될 수있는 성공합니다. 함수의 목적은 프로그램의 출력을 확인하고 실패하면 재 시도하는 것이므로 프로그램이 재 시도가 부족해서 검사에 실패하면 "성공적으로"반환하는 것이 이상하게 보입니다. 대신 예외를 발생시키는 것을 고려하십시오.for _ in range(retry): # ... if condition: break # ... else: raise ValueError("Failed to run program successfully, <some useful information about ret, output, etc.>") return output # Only output, since ``ret`` is guaranteed to be 0Pycharm 및 잠재적으로 다른 Python 스타일러는 사용하지 않는 이름이 지정된 변수를 사용하여 화를 낼 수 있습니다
i. 다음으로 교체하는 것이 좋습니다_.for _ in range(retry): # ...cmd check_output...파이썬이def.를 사용하기 때문에 나는 단지 오타 라고 가정 할 것 입니다 .독 스트링을 작성하세요!
다시 말하지만, 위의 모든 것이 개선 된 것이 아니라 단지 대안이라고 생각할 수 있습니다. 모두 따라 갔다면 다음과 같은 결과가 나올 수 있습니다.
def check_output_and_retry(cmd, check_output: lambda out: True, delay=1, retry=3):
"""Runs command until it succeeds. Raises a ValueError if it can't get the program to succeed.
Args:
cmd (str): The command to run
check_output (callable): A function that takes the output string and returns whether or not it's ok
delay (int|float): The number of seconds to wait between attempts
retry (int): The number of times to try running the command before failing
Returns:
str: The program output. The program return code is guaranteed to be 0.
"""
for _ in range(retry):
# Run the given command.
ret, output = execute_cmd(cmd)
status_ok = ret == 0
output_ok = check_output(output)
if status_ok and output_ok:
break
time.sleep(delay)
else:
raise ValueError(f"Program failed to execute within {retry} attempts (status: {ret}: {output}")
# Return value will be cmd output, since the return code is guaranteed to always be 0
return output