[Edu-sig] Re: [Idle-dev] Weird error when pydoc.help is added to builtin from site.py

Guido van Rossum guido@digicool.com
Tue, 12 Jun 2001 12:21:27 -0400


> Import pydoc; pydoc.help definitely works. In fact, adding help to the
> builtins works from my PYTHONSTARTUP file or interactively, but not from
> site.py. That's what made it so weird, at least to me. But getting it loaded
> as part of site was our goal. I'll step through the code when I get a spare
> hour (or two or three <g>).
> 
> >>> import __builtin__
> >>> from pydoc import help
> >>> __builtin__.help = help
> >>> del help
> >>> del __builtin__
> >>> help
> 
> Welcome to Python 2.1!  This is the online help utility.
> 
> If this is your first time using Python, you should definitely check out
> the tutorial on the Internet at http://www.python.org/doc/tut/.
> 
> Enter the name of any module, keyword, or topic to get help on writing
> Python programs and using Python modules.  To quit this help utility and
> return to the interpreter, just type "quit".
> 
> To get a list of available modules, keywords, or topics, type "modules",
> "keywords", or "topics".  Each module also comes with a one-line summary
> of what it does; to list the modules whose summaries contain a given word
> such as "spam", type "modules spam".
> 
> help>

Thanks, that helps!  I think I've nailed your problem now.

The problem is that you are importing pydoc in site.py.  The site
module is imported by Python before IDLE has created its windows.
This means that sys.stdin and sys.stdout still point to the default
stdin and stdout of the process -- which don't really exist, since
IDLE doesn't run in a DOS box.  (I predict that if you run IDLE in a
DOS box, help() will "work" using the DOS box for its input and
output.)

One solution would be to fix pydoc so that it doesn't "freeze" the
values of sys.stdin and sys.stdout at the time it is imported.

But a better solution (I think) is to add this to site.py:

  class _Helper:
      def __repr__(self):
          return "Please type help() for interactive help."
      def __call__(self, *args, **kwds):
          import pydoc
          return pydoc.help(*args, *kwds)

  help = _helper()

This means that you have to type 'help()' instead of 'help' to get
help, but it avoids a whole bunch of other issues with the help object
as well, and it is consistent with the behavior of 'quit', 'exit' and
(especially) 'license'.  Note that 'license' faces a similar problem
and uses the same solution (the repr() message reminds the user of the
proper way to invoke it).

I find this much cooler than the hack that Ping proposed. :-)

--Guido van Rossum (home page: http://www.python.org/~guido/)