我正在尝试使用 python 代码来模拟 *nix 系统的“tail”命令。
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
但是,如果我在使用时间模块的行之后注释行,则会抛出错误。
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
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
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
感谢您的回复。
请您参考如下方法:
简答题
第一个是实例化生成器(但不将其分配给变量),第二个是函数调用。
长答案
这是因为 python 的动态类型检查,当你有 yield 语句时,你的函数表现为一个生成器,这一行 -
tail(open(sys.argv[1],'r'))
意味着您正在实例化生成器而不是调用函数。当您将此实例分配给某个变量并调用生成器的 next 方法时,您会遇到该错误,该生成器实际上会启动它,即 -
t = tail(open(sys.argv[1],'r')) # t is a generator here
t.next()
另一种情况下,您删除了 yield 语句,它开始表现为正常函数,这意味着 - tail(open(sys.argv[1],'r')) 现在是一个函数调用,因此它抛出了一个错误。
我所说的动态是指 python 在到达该语句之前不会检查这些类型的错误,而在第一种情况下则不会。
