为什么我的Python交互式控制台无法正常工作?

7 投票
1 回答
1721 浏览
提问于 2025-04-16 06:09

我做了一个非常简单的互动控制台,想在一个复杂的网页抓取应用中使用。它的样子是这样的:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os, sys, codecs, code
sys.__stdout__ = codecs.getwriter('utf8')(sys.__stdout__)
sys.__stderr__ = codecs.getwriter('utf8')(sys.__stderr__)

if 'DEBUG' in os.environ:
    import pdb 
    import sys 
    oeh = sys.excepthook
    def debug_exceptions(type, value, traceback):
        pdb.post_mortem(traceback)
        oeh(type, value, traceback)
    sys.excepthook = debug_exceptions

class CLI(code.InteractiveConsole):
    def __init__(self, locals=None, filename="<console>", histfile=None):
        code.InteractiveConsole.__init__(self, locals, filename)
        try:
            import readline
        except ImportError:
            pass
        else:
            try:
                import rlcompleter
                readline.set_completer(rlcompleter.Completer(locals).complete)
            except ImportError:
                pass
            readline.parse_and_bind("tab: complete")
        self.interact()

if __name__ == "__main__":
    hello="I am a local"
    CLI(locals=locals())

如果我从另一个简单的应用程序调用它,它工作得很好:

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import os, sys, codecs, cli
sys.__stdout__ = codecs.getwriter('utf8')(sys.__stdout__)
sys.__stderr__ = codecs.getwriter('utf8')(sys.__stderr__)

from cli import CLI

foo="i am a local"
CLI(locals=locals())

但是,当我从我的抓取框架中调用它时,这个框架目前是基于twill和mechanize的(虽然我打算换成gevent),当我以完全相同的方式调用这个控制台时,方向键和Tab键补全都不工作,实际上它的表现就像没有readline这个模块一样。我尝试重新加载readline模块,并直接传递parse_and_bind命令,但出于某种原因,它就是不正常工作。有没有什么提示或者建议,能告诉我是什么东西搞砸了,导致它不能按预期工作,还是我得把所有外部模块都去掉,然后一个一个加回去看看发生了什么?

我对twill有点怀疑,因为它有自己的基本控制台,但如果有人知道发生了什么,我会很高兴知道。

哦,还有,请不要评论我对stderr和stdout的处理,那只是一些模板代码,放在python文件里,我总是从utf8控制台运行它们,这不是我想问的内容……

1 个回答

3

好的,我发现问题是我自己造成的。之前我用的老代码在某些情况下会导致问题,我直到后来才注意到这一点:

sys.stdout = codecs.getwriter('utf8')(sys.stdout)
sys.stderr = codecs.getwriter('utf8')(sys.stderr)

那段老代码还留在我自己的一个文件里,我把它改成了更简单的版本:

sys.__stdout__ = codecs.getwriter('utf8')(sys.__stdout__)
sys.__stderr__ = codecs.getwriter('utf8')(sys.__stderr__)

或者干脆把它删掉,因为其实这个文件根本不需要这段代码,这样问题就解决了。

撰写回答