2015-01-17 8 views
1

과제는 다음과 같습니다 : "ping 8.8.8.8"과 같은 가장 기본적인 형식을 사용하여 파이썬으로 핑을 보내보십시오. 얼마 후 ping 명령을 종료하십시오 (터미널에서 Ctrl + C를 눌러서 출력을 얻습니다). ping 통계를 보여주는 마지막 몇 줄의 출력은 특히 중요합니다.무한정한 시간 동안 ping을하고 파이썬에서 출력을 얻으십시오.

두 가지 방법이 시도했지만 작동하지 않았습니다. 내 OS 버전은 Mac OS X 10.10.1입니다.

첫 번째 방법은 모듈 pexpect를 사용하고, 나는 중지를 요청하지 않았지만 핑은 약 17 초 후에 중지됩니다 :

import pexpect 
import time 
child = pexpect.spawn('ping 8.8.8.8') 
(x, y) = child.getwinsize() 
print x 
print y 
time.sleep(21) 
child.terminate() 
x = child.read() 
print x 

두 번째 방법은 모듈의 하위 프로세스 및 핑 출력의 마지막 몇 줄의 손실을 사용합니다 :

import time 
from subprocess import PIPE, Popen 
child = Popen(['ping', '8.8.8.8'], stdin = PIPE, stdout = PIPE, stderr = PIPE) 
time.sleep(5) 
child.terminate() 
x = child.stdout.read() 
print x 
x = child.stderr.read() 
print x 

나는 어떤 도움을 주셔서 감사합니다! "ping -c XXX"는 허용되지 않습니다.

+0

관련 : [? 중지하지 않고 파이썬에서 프로세스 출력을 읽는 중지] (http://stackoverflow.com/a/4418891/4279)가 첫 번째 방법이 실패 – jfs

+0

이유가 있기 때문입니다 당신은 출력을 읽을 필요 pty 버퍼가 너무 작기 때문에, 출력을 버퍼 밖으로 이동시키기 위해 readline()을 계속 사용해야합니다. – brokenMotor

답변

0

두 번째 해결책은 훌륭합니다. 원하는 동작을 얻는 데 한 가지 문제가 있습니다 (ping의 "결론"을 얻음). 프로세스에 잘못된 신호를 보내고 있습니다.

쉘에서 프로세스를 종료하면 전통적으로 SIGINT 신호를 보냅니다. "bash - How does Ctrl-C terminate a child process?"을 참조하십시오. 이렇게하면 프로세스가 "마무리"(예 : 임시 파일 정리, 디버그 정보 제공) 할 수 있습니다. 현재 사용중인

import signal 

# Open process 

child.send_signal(signal.SIGINT) 

# Provide some time for the process to complete 
time.sleep(1) 

# Echo output 

Popen.terminate는하는 SIGTERM 대신 SIGINT 보냅니다.

+0

감사! 나는 투표에 대한 충분한 명성이 없다는 것이 유감이다. – brokenMotor

+0

@ user3186925 환영합니다. 질문에 대한 답변이 있으면 체크 표시를 사용하여이 대답을 수락 할 수 있습니다. 이것은 미래의 독자들이 그것을 발견하고 사이트를 더 가치있는 자원으로 만드는 데 도움이됩니다. –

+0

'SIGINT' 제안에 대한 Upvote가 있지만 "당신이 가진 두 번째 해결책은 훌륭합니다."* 해결책은 데이터 종속 버그를 야기합니다. 출력을 생성하는 동안 하위 프로세스가 차단 될 수 있습니다. 그것은 단순한 규칙에 위배됩니다 :'PIPE'를 사용하면; 파이프에서 읽어야합니다 ("* 무기한 * 시간"은 출력이 OS 파이프 버퍼보다 ​​클 수 있음을 나타냄). – jfs

0

Popen.terminate()는 Posix OS에서 SIGTERM을 보냅니다. 그러나 기본적으로 CTRL + C는 SIGINT를 보냅니다.

... 
import signal 
... 
time.sleep(5) 
child.send_signal(signal.SIGINT) 
... 
+0

감사합니다. 나는 투표에 대한 충분한 명성이 없다는 것이 유감이다. – brokenMotor

1

ping는 즉시이 (내 시스템에 ~ 65K)의 표준 출력의 OS 파이프 버퍼를 채우고로 코드 차단 : 그래서 CTRL + C를 눌러 같은 비슷한 동작을 얻기 위해, 당신은 이런 식으로 뭔가를 할 수 있습니다.

#!/usr/bin/env python 
import signal 
from subprocess import Popen, PIPE 
from threading import Timer 

child = Popen(['ping', '8.8.8.8'], stdin=PIPE, stdout=PIPE, stderr=PIPE) 
Timer(5, child.send_signal, [signal.SIGINT]).start() # Ctrl+C in 5 seconds 
out, err = child.communicate() # get output 
print(out.decode()) 
print('*'*60) 
print(err.decode()) 
+0

올바른 방법 –

+0

답변 해 주셔서 감사합니다. 내가 오랫동안 ping을 실행하고 싶다면 하루 동안 어쩌면 내가 어떻게해야합니까? 파일에 출력을 쓰는 것일까 요? Popen.communicate() 또는 Popen.stdout.read()를 사용하는 것 같습니다. PIPE에 쓰지 않기 때문에 중요하지 않습니다. 어떤 제안? – brokenMotor

+0

@ user3186925 : 코드는 1 일 동안 그대로 작동해야합니다 ('5'를 '86400'으로 대체). 1. Timer(). start()는 즉시 (* sleep과는 달리) *를 반환합니다. 2. .communicate()는 * stdout과 stderr를 동시에 읽습니다. 서브 프로세스가 실행 중일 때 출력을 보려면, [Python : subprocess.communicate()에서 스트리밍 입력 읽기] (http://stackoverflow.com/a/17698359/4279)를 참조하십시오. – jfs