在try ... except块中处理generator.send()时出现异常

时间:2012-08-16 21:08:15

标签: python try-catch generator yield except

filename = 'tempfile'

def tail(filename):
    fd = open(filename)
    while True:
        line = fd.readline()
        if not line:
            continue
        else:
            if filename != 'uh':
                yield line
            else:
                print 'Returning f to close the file'
                yield fd


try:
    genObj = tail(filename) 
    valfromgen= genObj.next()
    while valfromgen:
        print valfromgen
        valfromgen= genObj.next()
except:
    traceback.print_exc()
    try:
        fd_Got_Back = genObj.send('uh')
        fd_Got_Back.close()
    except:
        traceback.print_exc()

代码的意图:我只在生成器函数中打开文件,而不是在它之外,但是,我想通过使用'send'来关闭生成器函数之外的文件。

我要做的是:从unix复制tail -f

我是怎么做的:

  1. 以读取模式打开临时文件。
  2. 如果临时文件中写有1个新行(我将继续手动编写并使用记事本保存tempfile),则生成新写入的行。
  3. 问题:

    问题是,如果按 Ctrl + C (即SIGTERM),我正试图检查如何从此python代码中关闭打开的tempfile )当这个Python代码在命令提示符下运行时。为了模拟这个,我在tail函数中打开了tempfile,并且每当出现异常时(当我按下 Ctrl + <时系统会引发异常kbd> C ),控件应该在1 st 中除外。然后,从这里,我正在尝试向生成器函数uh发送值tail,以便它应该生成打开的文件的文件描述符,我可以使用它来关闭打开的临时文件。

    PS:我期待一个解决方案,我只在生成器函数中打开文件,而不是在它之外。

2 个答案:

答案 0 :(得分:0)

我认为你误解了“发送”是如何工作的。发送只是使生成器在下一次迭代时产生该值。它不会更改原始参数的值。然后,您可以出于某种目的使用该值。所以你可以制作你的代码:

filename = 'tempfile'

def tail(filename):
    fd = open(filename)
    while True:
        line = fd.readline()
        if not line:
            continue
        else:
            x = (yield line)
            if (x == 'uh'):
                print 'Returning f to close the file'
                yield fd


try:
    genObj = tail(filename) 
    valfromgen= genObj.next()
    while valfromgen:
        print valfromgen
        valfromgen= genObj.next()
except:
    traceback.print_exc()
    try:
        genObj.send('uh').close()
    except:
        traceback.print_exc()

答案 1 :(得分:0)

我已经找到了问题,我遇到了这个问题: -

  1. 当我按下Ctrl + C(在Windows上)时,KeyboardInterrupt实际上发生在fd.readline()中。所以,我只是尝试了...除了那里,所以只要按下Ctrl + C,生成器函数就会产生文件描述符。如果没有KeyBoardInterrupt,那么只需从tempfile
  2. 打印一条新读取的行
  3. 使用主体中的isinstance()检查此文件描述符,如果发现它是文件,那么,我正在关闭文件以及生成器
  4. PS :(这个KeyboardInterrupt在Linux上可能会有所不同......可能会引发SigTerm,但请检查。所以,为了使代码通用,只需删除KeyBoard Interrupt并使用正常除)

    import sys,  traceback
    
    filename = 'tempfile'
    
    def tail(filename):
        fd = open(filename)
        while True:
            try:
                line = fd.readline()
            except KeyboardInterrupt:
                print 'keyboard interrupt here'
                yield fd
            if not line:
                continue
            else:
                yield line
    
    
    try:
        genObj = tail(filename) 
        valfromgen= genObj.next()
        while valfromgen:       
            if isinstance(valfromgen, file):
                print 'Closing this file now as `tail` yielded a file descriptor'
                valfromgen.close()
                genObj.close()
                break
            print 'Yielded line: ', valfromgen
            valfromgen= genObj.next()
    
        print 'Just in order to check that things are in order, the following line will raise StopIteration. If it raises, it means we are good.'
        print genObj.next()
    except:
        traceback.print_exc()