3

在现有的代码片段中,我有

import sys
from code import InteractiveConsole


class FileCacher:
    "Cache the stdout text so we can analyze it before returning it"
    def __init__(self):
        self.reset()

    def reset(self):
        self.out = []

    def write(self, line):
        self.out.append(line)

    def flush(self):
        output = '\n'.join(self.out)
        self.reset()
        return output


class Shell(InteractiveConsole):
    "Wrapper around Python that can filter input/output to the shell"
    def __init__(self):
        self.stdout = sys.stdout
        self.cache = FileCacher()
        InteractiveConsole.__init__(self)
        return

    def get_output(self):
        sys.stdout = self.cache

    def return_output(self):
        sys.stdout = self.stdout

    def push(self, line):
        self.get_output()
        # you can filter input here by doing something like
        # line = filter(line)
        InteractiveConsole.push(self, line)
        self.return_output()
        output = self.cache.flush()
        # you can filter the output here by doing something like
        # output = filter(output)
        print output  # or do something else with it
        return

if __name__ == '__main__':
    sh = Shell()
    sh.interact()

如果 IPython 可用,我如何修改它以使用 IPython 的交互式 shell,如果可能的话不更改其余代码。

我尝试将第 2 行from code import InteractiveConsole替换为,from IPython.core import interactiveshell as InteractiveConsole但显然,它不是一个可直接互换的类。

什么是最好的方法来做到这一点(对代码库的其余部分的改变最小)除了存在时IPython优先使用code模块IPython吗?

4

2 回答 2

1

这是我自己的尝试:-

import sys
from code import InteractiveConsole

class FileCacher:
    "Cache the stdout text so we can analyze it before returning it"
    def __init__(self):
        self.reset()

    def reset(self):
        self.out = []

    def write(self, line):
        self.out.append(line)

    def flush(self):
        output = '\n'.join(self.out)
        self.reset()
        return output


class Shell(InteractiveConsole):
    "Wrapper around Python that can filter input/output to the shell"
    def __init__(self):
        self.stdout = sys.stdout
        self.cache = FileCacher()
        InteractiveConsole.__init__(self)
        return

    def get_output(self):
        sys.stdout = self.cache

    def return_output(self):
        sys.stdout = self.stdout

    def push(self, line):
        self.get_output()
        # you can filter input here by doing something like
        # line = filter(line)
        InteractiveConsole.push(self, line)
        self.return_output()
        output = self.cache.flush()
        # you can filter the output here by doing something like
        # output = filter(output)
        print output  # or do something else with it
        return

if __name__ == '__main__':
    try:
        import IPython
        IPython.embed()
    except:
        sh = Shell()
        sh.interact()

这似乎工作正常,但我可能丢失了cachestdout定义方法/功能。

欢迎任何批评、编辑和改进建议!

于 2012-04-24T15:32:05.613 回答
0

我不是一个大专家(所以如果我错了请不要投反对票),但我认为你可以选择类似的东西

try: from IPython.core import interactiveshell as InteractiveConsole #facade code here,如果需要,除了 ImportError: from code import InteractiveConsole #fallback case

这样,您将获得您的code.InteractiveConsole,如果它存在并且IPython.core.interactiveshell以其他方式重新映射为InteractiveConsole. 无论如何,您都必须更改方法名称和签名,或者尝试构建某种外观或适配器。

一种可能的方法是将所有必需的函数调用别名到您的命名空间并使用此别名。与“外观”代码相比,您只需定义具有相同签名(名称和参数列表)的函数并让它们调用interactiveshell函数:

try:
     from IPython.core import interactiveshell as InteractiveConsole
     def func1(a,b,c):
          InteractiveConsole.some_other_func(a,b,c)
except ImportError:
     from code import InteractiveConsole        #fallback case
     func1 = InteractiveConsole.func1

...
func1(a,b,c)
于 2012-04-24T15:25:20.210 回答