简体   繁体   English

在try…except块中处理generator.send()时发生异常

[英]Exception while handling generator.send() in try…except block

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()

Intention of the code: I have opened the file in the generator function only and not outside it, but, I want to close that file outside the generator function by using 'send' probably. 代码的意图:我仅在生成器函数中打开了文件,而不是在文件外部打开了文件,但是,我可能想通过使用“发送”来关闭文件在生成器函数之外的文件。

What I am trying to do: Replicating tail -f from unix. 我想做的是:从unix复制tail -f

How I am trying to do: 我要如何做:

  1. Open a tempfile in read mode. 在读取模式下打开一个临时文件。
  2. If the tempfile has 1 new line written in it (which I'll keep on writing manually and saving tempfile using notepad) , yield the newly written line. 如果临时文件中写入了1行(我将继续手动编写并使用记事本保存tempfile) ,请产生新行。

Problem: 问题:

The problem is that I'm trying to check how I can close the opened tempfile from this python code if I press Ctrl + C (ie SIGTERM) when this Python code runs in command prompt. 问题是,如果我在命令提示符下运行此Python代码时按Ctrl + C (即SIGTERM) ,则试图检查如何从此python代码关闭打开的临时文件。 In order to emulate this, I have opened the tempfile in the tail function, and whenever there is an exception (which will be raised by the system when I press Ctrl + C ) , the control should go in the 1 st except. 为了模拟这一点,我已经在打开了临时文件tail功能,每当有一个例外(这将是由系统当我按下Ctrl + C被升高)时,控制应在第1去除了。 Then, from here, I'm trying to send a value uh to the generator function tail , so that it should yield the file descriptor of the opened file which I can use to close the opened tempfile. 然后,从这里开始,我尝试将值uh发送到生成器函数tail ,以便它应产生已打开文件的文件描述符,可用于关闭已打开的tempfile。

PS: I expect a solution where I have opened the file in the generator function only and not outside it. PS:我希望有一个解决方案,其中我只能在generator函数中打开文件,而不能在它外部打开。

I think You're misunderstanding how "send" works. 我认为您误解了“发送”的工作方式。 Send simply causes a generator to yield that value on its next iteration. 发送只是使生成器在下一次迭代时产生该值。 It does not change the value of the original parameters. 它不会更改原始参数的值。 You can then use that yielded value for some purpose. 然后,您可以出于某些目的使用该产生的值。 So you could make your code: 因此,您可以编写代码:

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()

I have figured out the problem where I was stuck and I have come up with this solution:- 我已经解决了卡住的问题,并提出了以下解决方案:-

  1. When I press Ctrl + C (on Windows), the KeyboardInterrupt actually happens in fd.readline(). 当我按Ctrl + C(在Windows上)时,KeyboardInterrupt实际上发生在fd.readline()中。 So, I just placed a try...except there, so that the generator function yields the file descriptor whenever Ctrl + C is hit. 因此,我只是尝试了一下...除了那里,所以只要按Ctrl + C,生成器函数就会产生文件描述符。 If there is no KeyBoardInterrupt , then, just print a newly read line from tempfile 如果没有KeyBoardInterrupt,那么只需从tempfile打印一个新读取的行
  2. This file descriptor is checked using isinstance() in the main body, and if it is found to be a file, then, I'm closing the file as well as the generator 使用主体中的isinstance()检查此文件描述符,如果发现它是文件,那么我将关闭文件以及生成器

PS : (this KeyboardInterrupt might vary on Linux..probably SigTerm will be raised, but, please check. So, in order to make the code generic, just remove KeyBoard Interrupt and use just normal except) 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()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM