[IPython-user] pyreadline, code.InteractiveConsole and tab completion on Windows
Thomas Heller
theller@ctypes....
Wed Apr 8 14:38:17 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?
>
>> 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 a running demo script now; it was easier than I thought first.
Basically the trick was to open the input/output streams as "CONIN$"
and "CONOUT$".
<snip ---interp.pyw--->
# Thomas Heller <theller@ctypes.org>, 2009/04/07
#
# This script demonstrated how to use tab-completion with pyreadline
# on Windows in an interactive interpreter implemented by the code
# module. It also works when started from a GUI-program (as .pyw
# script, for example).
import code, ctypes, sys
def main():
# Allocate a console if there isn't one
ctypes.windll.kernel32.AllocConsole()
# Create new standard streams
sys.stdin = open("CONIN$", "r")
# Buffering on the output streams must be switched off explicitely
# (is this a bug in the code module not calling flush()?)
sys.stdout = open("CONOUT$", "w", 0)
sys.stderr = open("CONOUT$", "w", 0)
import rlcompleter, readline
# pyreadline.unicode_helper (v 1.5) has one buglet: sys.stdout, as
# defined above, has sys.stdout.encoding == None. pyreadline
# doesn't like this, so we set it here.
#
# I've made several experiments with codecs.open(...) to create
# sys.std[in|out|err] but it didn't work.
import pyreadline.unicode_helper
input_cp = ctypes.windll.kernel32.GetConsoleCP()
pyreadline.unicode_helper.pyreadline_codepage = "cp%d" % input_cp
# Create a namespace for the interactive interpreter, this must
# also be passed to the completer because otherwise the completer
# would use the __main__ namespace.
namespace = {}
readline.parse_and_bind("tab: complete")
# Override the default completer.
readline.set_completer(rlcompleter.Completer(namespace).complete)
# Start the interpreter.
code.interact(local=namespace)
if __name__ == "__main__":
main()
<snip>
> If you have any ideas on how to change things to make it more useful for
> you please let me know.
As you can see in the comments above, one change to pyreadline/unicode_helpers.py
would be nice, because the sys.stdin object that I create above has a .encoding
attribute which is None:
diff -u c:\python24\lib\site-packages\pyreadline\unicode_helper.py~ c:\python24\lib\site-packages\pyreadline\unicode_helper.py
--- c:\python24\lib\site-packages\pyreadline\unicode_helper.py~ Wed Apr 08 19:37:36 2009
+++ c:\python24\lib\site-packages\pyreadline\unicode_helper.py Wed Apr 08 19:37:36 2009
@@ -13,6 +13,9 @@
#stdout with stdout collector
pyreadline_codepage="ascii" #assume ascii codepage
+if pyreadline_codepage is None:
+ pyreadline_codepage="ascii"
+
def ensure_unicode(text):
"""helper to ensure that text passed to WriteConsoleW is unicode"""
if isinstance(text, str):
> /Jörgen
--
Thanks,
Thomas
More information about the IPython-user
mailing list