[IPython-user] pyreadline, code.InteractiveConsole and tab completion on Windows

Thomas Heller theller@ctypes....
Tue Apr 7 15:20:38 CDT 2009


Jörgen Stenarson schrieb:
> Thomas Heller skrev:
>> Jörgen Stenarson schrieb:
>>> Thomas Heller skrev:
>> My Python console isn't started in the usual way because my application is
>> a Windows application.
>> When a certain button is pressed in the GUI, a win32 console is allocated,
>> sys.std[in|out|err] are initialized to readers/writers that read and write to
>> from/to the corresponding console handles, and so on.  Basically the code goes
>> like this:
>> 
>>     windll.kernel32.AllocConsole()
>>     windll.kernel32.SetConsoleTitleA(str(title))
>> 
>>     sys.stdout = writer(windll.kernel32.GetStdHandle(-11))
>>     sys.stderr = writer(windll.kernel32.GetStdHandle(-12))
>>     sys.stdin = reader(windll.kernel32.GetStdHandle(-10))
>> 
> out of curiosity what is reader and writer?

Here it is (OutputDebugString is only called for debugging):

<snip>
# Apparently things only work correctly when we are feeding "MBCS"
# encoded strings to the evaluator, and expect strings that are "MBCS"
# encoded.  To correctly read and write from and to the console, we
# have to convert them from and to the console's current codepage.

class writer(object):
    def __init__(self, handle):
        self.handle = handle
        self.encoding = "cp%s" % windll.kernel32.GetConsoleOutputCP()

    def write(self, text):
        bytes_written = c_ulong()
        if isinstance(text, unicode):
            windll.kernel32.OutputDebugStringW(text)
            windll.kernel32.WriteConsoleW(self.handle,
                                          text,
                                          len(text),
                                          byref(bytes_written),
                                          None)
        else:
            windll.kernel32.OutputDebugStringA(text)
            text = text.decode("mbcs").encode(self.encoding)
            windll.kernel32.WriteConsoleA(self.handle,
                                          text,
                                          len(text),
                                          byref(bytes_written),
                                          None)

class reader(object):
    def __init__(self, handle):
        self.handle = handle
        self.encoding = "cp%s" % windll.kernel32.GetConsoleCP()

    def read(self, size=None):
        if size is None:
            size = 256
        buf = create_unicode_buffer(size)
        chars_read = c_ulong()
        windll.kernel32.ReadConsoleW(self.handle,
                                     buf,
                                     len(buf),
                                     byref(chars_read),
                                     None)
        data = buf.value.replace("\r\n", "\n")
        # ^Z plus line feed means EOF:
        if data == "\x1a\n":
            return ""
        return data.encode("mbcs")

##    def read(self, size=None):
##        if size is None:
##            size = 256
##        buf = create_string_buffer(size)
##        chars_read = c_ulong()
##        windll.kernel32.ReadConsoleA(self.handle,
##                                     buf,
##                                     len(buf),
##                                     byref(chars_read),
##                                     None)
##        data = buf.value.replace("\r\n", "\n")
##        if data == "\x1a\n":
##            return ""
##        return data.decode(self.encoding).encode("mbcs")

    def readline(self):
        return self.read()


>>     from code import InteractiveConsole
>> 
>>     console = InteractiveConsole(ns)
>>     console.interact(title)
>> 
>> reader(handle) and writer(handle) are instances that read and write from/to
>> the console handles with the windll.kernel32.WriteConsole[A|W]()
>> and windll.kernel32.ReadConsoleW() windows functions.
>> So, is it possible to plug pyreadline into this system somehow?
>> 
> 
> I have no idea if it is possible. I'm sorry to say this is at the edge 
> of my comfort level in win32 programming.
> 
> Something to investigate would be to see if you can patch in a handle to 
> your console in the active Console object. It can be found in 
> readline.rlmain.rl.console. Check the __init__ method of Console in 
> readline.console.console.py to see what configurations are done on startup.

Thanks for your tips; I will do my best...

> If you have any ideas on how to change things to make it more useful for 
> you please let me know.

and report back when I have something.

> 
> /Jörgen

Thanks again,
Thomas



More information about the IPython-user mailing list