简体   繁体   English

如果存在IPython,则将IPython与代码模块互换使用

[英]Using IPython interchangeably with code module if IPython exists

In an existing code snippet, I have 在现有的代码段中,我有

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()

How do I modify this to use IPython's interactive shell if IPython is available without changing the rest of the code if possible. 如果IPython可用,如何在不更改其余代码的情况下修改它以使用IPython的交互式外壳。

I attempted swapping out line 2 from code import InteractiveConsole with from IPython.core import interactiveshell as InteractiveConsole but obviously, it's not a directly interchangeable class. 我尝试将from code import InteractiveConsole第2行与from IPython.core import interactiveshell as InteractiveConsole换出from IPython.core import interactiveshell as InteractiveConsole但是显然,它不是直接可互换的类。

What's the best way to do this (with minimal change to the rest of the code base) with a try except and using IPython in preference over code module when IPython exists? 尝试进行此操作的最佳方法(对代码库的其余部分进行最少的更改)尝试除IPython存在之外,并优先于code模块使用IPython进行此操作吗?

Here's my own attempt:- 这是我自己的尝试:

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()

which seems to work fine but I probably lost the cache and stdout custom methods/functionalities. 这似乎工作正常,但我可能会丢失cachestdout自定义方法/功能。

Any criticism, edits and improvement suggestions welcome! 欢迎任何批评,编辑和改进建议!

I'm not a big expert (so plese don't downvote if I'm wrong), but I think you can go with something like 我不是专家,所以如果我错了,请不要投票,但是我认为您可以选择

try: from IPython.core import interactiveshell as InteractiveConsole #facade code here, if needed except ImportError: from code import InteractiveConsole #fallback case 尝试:从IPython.core从此处将Interactiveshell作为InteractiveConsole #facade代码导入,如果需要的话,除了ImportError:从代码中导入InteractiveConsole #fallback案例

This way you'll get your code.InteractiveConsole if it's present and IPython.core.interactiveshell otherwise remapped as InteractiveConsole . 这样,您将获得code.InteractiveConsole如果存在),而IPython.core.interactiveshell否则将重新映射为InteractiveConsole You'll have to change method names and signatures anyway, or try build some kind of facade or adapter. 无论如何,您都必须更改方法名称和签名,或者尝试构建某种外观或适配器。

One possible way is to alias all required function calls into your namespace and use this aliases. 一种可能的方法是将所有必需的函数调用别名到您的名称空间中,并使用此别名。 Than in 'facade' code you'll just have to define functions with same signatures (names and parameter lists) and make them call interactiveshell functions: 比在“外观”代码中,您只需要定义具有相同签名(名称和参数列表)的函数,并使它们称为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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM