In Python 3.3 and newer, you can return a value from a generator; we use this in Tornado to have functions that call big and slow subprocesses (translate_part
below) without blocking the main thread, and also without having more than one of the big&slow functions running concurrently:
@gen.coroutine
def translate(self, text, lock):
parts = yield [translate_part(part, lock) for part in splitup(text)]
retval = "".join(parts)
return retval
To support Python 3.2, we changed it to the uglier, but equivalent:
@gen.coroutine
def translate(self, text, lock):
parts = yield [translate_part(part, lock) for part in splitup(text)]
retval = "".join(parts)
raise StopIteration(retval)
However, this is (understandably) deprecated after Python 3.5. But how do we support both Python 3.5+ and Python 3.2? It's impossible to do
if sys.version_info.minor<3:
raise StopIteration(retval)
else:
return retval
since Python 3.2 raises SyntaxError on "return retval", and of course
try:
return retval
except SyntaxError:
raise StopIteration(retval)
doesn't work. Is there a non-ugly solution to this, or do we have to maintain two versions?
https://www.python.org/dev/peps/pep-0479/ claims fixing things to be backwards-compatible is easy, but all their examples are of StopIteration's/return's without values.