#1
  1. Wacky hack
    Devshed Novice (500 - 999 posts)

    Join Date
    Apr 2001
    Location
    London, England
    Posts
    513
    Rep Power
    14

    Returning a value without breaking from function?


    Hullo,

    I'm trying to solve a bit of a conundrum here. I have a function (well, to be precise a class method) that opens a pipe and uses a while loop to go through the output line by line. It needs to return some information from each line as it comes, and previously I've achieved that by having a function called "printProgress" that is called in the while loop and that, well, prints the progress!

    The problem is that for various reasons this isn't satisfactory any more. I need to be able to do something like:

    Code:
    def run():
        (open the pipe, etc.)
        while pipe.read(1000):
            return
    
    while run():
        (do something here)
    The problem of course is that "return" will break from the function on the first call.

    I've read a little about yield, and think it might be what I'm looking for, but I can't figure out how to use it. I've also considered opening a fifo, but that seems a little extreme.

    Ideas?
  2. #2
  3. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2002
    Location
    Norwich, UK
    Posts
    53
    Rep Power
    13
    From the looks of this page it seems yield does what you want. There's a few examples/explanations on it's usage which might help.
  4. #3
  5. Hello World :)
    Devshed Frequenter (2500 - 2999 posts)

    Join Date
    Mar 2003
    Location
    Hull, UK
    Posts
    2,537
    Rep Power
    69
    Yeah, yield is looking pretty good. What we need added is a return that keeps going without exiting. Yield would be nicer still if it returned a readable value instead of a <generator.. but it works, you just need to call list or tuple on the function (you can't make a string or dictionary this way which sucks, infact i can't).

    Can't see me ever using it unless i have too i really don't like how it works..

    Mark.
  6. #4
  7. Wacky hack
    Devshed Novice (500 - 999 posts)

    Join Date
    Apr 2001
    Location
    London, England
    Posts
    513
    Rep Power
    14
    I can't get how it works at the moment; every time I experiment I get an error. I'm going to have to find some examples, since the python docs only seem to mention it in the "language lawyers" section.
  8. #5
  9. Wacky hack
    Devshed Novice (500 - 999 posts)

    Join Date
    Apr 2001
    Location
    London, England
    Posts
    513
    Rep Power
    14
    Aha! I correct myself... here's a working example:

    Code:
    # This is needed in Python < 2.3
    from __future__ import generators
    import os, popen2
    
    def run(self, program, arguments):
    	"""Runs a program; supply program name (string) and arguments (list)"""
    	command = arguments
    	command[:0] = [program]
    
    	self.pipe = popen2.Popen4(command)
    	pid = self.pipe.pid
    	while 1:
    		line = self.pipe.fromchild.read(1000)
    		if not line:
    			break
    		yield line
    
    	# Clean up process table
    	try:
    		self.kill_pipe()
    		os.waitpid(pid, os.WNOHANG)
    	except:
    		pass
    
    for line in run('runme', ['real', 'quick']):
    	print line
    That function lets me safely handle running external commands and parse the output line by line (in conjuction with another function to kill the pipe, kill_pipe()).

IMN logo majestic logo threadwatch logo seochat tools logo