[Python-ideas] Yielding from the command line

Martin Teichmann lkb.teichmann at gmail.com
Sun Sep 14 23:24:40 CEST 2014


Hi everyone,

since there seemed to be some interest in my idea of a
asyncio-enabled command line, I just sat down and wrote
it. I submitted the parts that would need to go into CPython
as Issue 22412 to  the Python bug tracker. I added a simple
command line interpreter, based on code.InteractiveConsole,
which will allow for uses like

>>> from asyncio import sleep
>>> yield from sleep(10)

The  following code is mostly a copy of InteractiveConsole, with
the appropriate yield froms stuck in (and comments removed.
Yeah!)

Greeting

Martin

Code follows:

from asyncio import get_event_loop, coroutine, input
from code import InteractiveConsole
import sys

class AsyncConsole(InteractiveConsole):
    def __init__(self, locals=None, filename="<console>"):
        super().__init__(locals, filename)
        self.compile.compiler.flags |= 0x1000

    @coroutine
    def runsource(self, source, filename="<input>", symbol="single"):
        try:
            code = self.compile(source, filename, symbol)
        except (OverflowError, SyntaxError, ValueError):
            self.showsyntaxerror(filename)
            return False

        if code is None:
            return True

        yield from self.runcode(code)
        return False

    @coroutine
    def runcode(self, code):
        try:
            yield from eval(code, self.locals)
        except SystemExit:
            raise
        except:
            self.showtraceback()

    @coroutine
    def push(self, line):
        self.buffer.append(line)
        source = "\n".join(self.buffer)
        more = yield from self.runsource(source, self.filename)
        if not more:
            self.resetbuffer()
        return more

    @coroutine
    def interact(self, banner=None):
        try:
            sys.ps1
        except AttributeError:
            sys.ps1 = ">>> "
        try:
            sys.ps2
        except AttributeError:
            sys.ps2 = "... "
        cprt = 'Type "help", "copyright", "credits" or "license" for
more information.'
        if banner is None:
            self.write("Python %s on %s\n%s\n(%s)\n" %
                       (sys.version, sys.platform, cprt,
                        self.__class__.__name__))
        elif banner:
            self.write("%s\n" % str(banner))
        more = 0
        while 1:
            try:
                if more:
                    prompt = sys.ps2
                else:
                    prompt = sys.ps1
                try:
                    line = yield from input(prompt)
                except EOFError:
                    self.write("\n")
                    break
                else:
                    more = yield from self.push(line)
            except KeyboardInterrupt:
                self.write("\nKeyboardInterrupt\n")
                self.resetbuffer()
                more = 0
            except SystemExit:
                return

if __name__ == "__main__":
    console = AsyncConsole()
    get_event_loop().run_until_complete(console.interact())


More information about the Python-ideas mailing list