如果存在IPython,则可以与代码模块交替使用IPython

时间:2012-04-24 14:55:41

标签: python ipython

在现有的代码段中,我有

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,如果可能的话,不用更改其余的代码。

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

执行此操作的最佳方法是什么(对代码库的其余部分进行最小的更改)除了在IPython存在code之后优先于IPython模块使用{{1}}之外?

2 个答案:

答案 0 :(得分: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自定义方法/功能。

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

答案 1 :(得分:0)

我不是一个大专家(如果我错了,请不要贬低),但我认为你可以选择

尝试:         从IPython.core导入interactiveshell作为InteractiveConsole         如果需要,在这里#facade代码    除了ImportError:         从代码导入InteractiveConsole #fallback case

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

一种可能的方法是将所有必需的函数调用别名放入命名空间并使用此别名。在'facade'代码中,您只需要定义具有相同签名(名称和参数列表)的函数,并使它们调用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)