2017-03-05 3 views
1

파이썬 코드를 따라 * nix 시스템의 '꼬리'명령을 시뮬레이트하려고했습니다.파이썬 생성기 : 주석 처리 후에 만 ​​표시되는 오류

import sys 
def tail(f): 
    print 'in tail with ',f 
    f.seek(0,2) 
    while True: 
     line = f.readline() 
     if not line: 
      time.sleep(0.1) 
      continue 
     yield line 

if(len(sys.argv) >= 2): 
    print 'calling tail' 
    tail(open(sys.argv[1],'r')) 
else: 
    print 'Give file path.\n' 

오류 (가져온 시간 모듈을 가져 오지 못함)가 발생했습니다. 그러나 이상한 점은 오류가 발생하지 않고 프로그램이 자동으로 종료된다는 것입니다. (주석 전) 출력 : 내가 시간 모듈을 사용하여 하나를 다음 줄을 주석 경우

$ python tail.py /var/log/dmesg 
calling tail 

그러나, 오류가 던져 않습니다. 오류가 하나 (코멘트하기 전에) 경우에 던져지고되지 않은 이유를

$ python tail.py /var/log/dmesg 
calling tail 
in tail with <open file '/var/log/dmesg', mode 'r' at 0x7fc8fcf1e5d0> 
Traceback (most recent call last): 
    File "tail.py", line 14, in <module> 
    tail(open(sys.argv[1],'r')) 
    File "tail.py", line 8, in tail 
    time.sleep(0.1) 
NameError: global name 'time' is not defined 

사람이 설명해주십시오 수 (주석 후)

import sys 
def tail(f): 
    print 'in tail with ',f 
    f.seek(0,2) 
    while True: 
     line = f.readline() 
     if not line: 
      time.sleep(0.1) 
     #  continue 
     # yield line 

if(len(sys.argv) >= 2): 
    print 'calling tail' 
    tail(open(sys.argv[1],'r')) 
else: 
    print 'Give file path.\n' 

출력? 통역관이 오는 즉시 오류가 발생해서는 안됩니까?

수정 프로그램 :

import sys 
import time 
def tail(f): 
    print 'in tail with ',f 
    f.seek(0,2) 
    while True: 
     line = f.readline() 
     if not line: 
      time.sleep(0.1) 
      continue 
     yield line 

if(len(sys.argv) >= 2): 
    print 'calling tail' 
    t = tail(open(sys.argv[1],'r')) 
    for i in t: 
     print i 
else: 
    print 'Give file path.\n' 

출력 : 응답

$ python tail.py hello.txt 
calling tail 
in tail with <open file 'hello.txt', mode 'r' at 0x7fac576b95d0> 
hello there 1 

hello there 2 

hello there 3 

감사합니다.

+0

if 조건이 만족스럽지 않습니다. (두 번째 호출에서) 선을 양보하지 않는 경우에만? – Peaceful

답변

3

단답형

첫번째는 발전기를 인스턴스화 (그러나 변수에 할당되지 않음)과 두 번째 함수 호출이다.


긴 대답

이 때문에 파이썬의 동적 유형 검사입니다 당신이 yield 문이있을 때, 당신의 함수는 발전기로 동작하고이 라인 -

tail(open(sys.argv[1],'r')) 

수단 당신은 입니다. 생성자 이 아닙니다.

t = tail(open(sys.argv[1],'r')) # t is a generator here 
t.next() 

당신이 yield 문을 제거하는 다른 경우, 그것은 시작 - 일부 변수에이 인스턴스를 할당하고 그것을 최대 즉, 어떤 실제로 화재 발생의 next 방법을 호출 할 때이 오류가 발생합니다 - tail(open(sys.argv[1],'r'))이 지금은 함수 호출이므로 정상적인 함수로 동작하므로 오류가 발생했습니다.

내가 동적 인 것을 의미하는 것은 파이썬이 이런 종류의 오류를 검사하지 않는다는 것입니다.이 문은 처음에는 그렇지 않았습니다.

+0

매우 명확하고 간결합니다. 감사. – dheerajSuthar

3

기능에 yield을 사용하면 생성자입니다. 생성자 함수는 다음 값이 요청 될 때만 포함 된 코드를 실행합니다. 단순히 생성기 함수를 호출하기 만하면 해당 생성기 개체가 생성됩니다. 그 객체를 루핑하는 것과 같이 아무 것도하지 않고 그렇게하면 아무 일도 일어나지 않을 것입니다.

yield을 제거하면 기능이 열심히 평가되므로 해당 코드가 실제로 실행됩니다.

실제로 발전기를 반복하면 readline()에 빈 줄이 생기면 오류가 발생합니다. 빈 줄은 파일의 끝에서만 발생할 수 있기 때문에 (빈 줄처럼 보이는 것은 사실 단일 줄 넘김 문자를 포함하고 있습니다), 루프에 넣는 것이 어차피 이해가되지 않습니다. 이 대신 :

while True: 
    line = f.readline() 
    if not line: 
     time.sleep(0.1) 
     continue 
    yield line 

사용이 :이의

for line in f: 
    yield line 

대신을 :

if(len(sys.argv) >= 2): 
    print 'calling tail' 
    tail(open(sys.argv[1],'r')) 

당신은 실제로 이런 일에, 발전기의 내용을 실행한다 :

if(len(sys.argv) >= 2): 
    print 'calling tail' 
    for line in tail(open(sys.argv[1],'r')): 
     print line 
+0

답장을 보내 주셔서 감사합니다. 딜레이와 루프는 'tail -f hello.txt'와 같이 Linux의 tail 명령어와 비슷한 동작을 할 수 있도록 입력을 대기합니다. 출력이있는 원본 게시물의 편집 내용을 확인하십시오. 다른 터미널의 hello.txt 파일에 텍스트를 동시에 추가했습니다. – dheerajSuthar