ipython是一个非常棒的工具, 即改进了python的命令行工具的代码输入不友好, 又给jupyter做了很好的铺垫。

感觉jupyter的notebook用起对代码执行和展示都比较好,但是对代码的可阅读性大大降低。

所以我想做一个插件,又有jupyter的执行方便,又保留python代码的可阅读性。

ipython项目是一个很好的借鉴,于是来看了下ipython的源码,我在github上面的ipython项目clone下来。

这个项目是python项目,也是大量的使用类的继承这些,不过整体来说,还是有很好的阅读性。

让我比较老火的是系统python环境的干扰,后来我新建了一个anaconda管理环境,总算是放心的调试了。

先看看代码:

代码入口为 IPython/__main__.py:

from IPython import start_ipython

start_ipython() # 就这句代码

主题代码是 IPython/terminal/ipapp.py 中的 TerminalIPythonApp 类

class TerminalIPythonApp(BaseIPythonApplication, InteractiveShellApp):

代码运行最多的是下面这个代码中的while循环:

def interact(self, display_banner=DISPLAY_BANNER_DEPRECATED):

        if display_banner is not DISPLAY_BANNER_DEPRECATED:
            warn('interact `display_banner` argument is deprecated since IPython 5.0. Call `show_banner()` if needed.', DeprecationWarning, stacklevel=2)

        self.keep_running = True
        while self.keep_running:
            print(self.separate_in, end='')
            try:
                code = self.prompt_for_code() #获取输入代码
            except EOFError:
                if (not self.confirm_exit) \
                        or self.ask_yes_no('Do you really want to exit ([y]/n)?','y','n'):
                    self.ask_exit()

            else:
                if code: 
                    self.run_cell(code, store_history=True) #执行输入代码并保存状态

最终执行代码的部分是另外一个core目录下的interactiveshell.py,IPython/core/interactiveshell.py文件中的run_code函数,最底层调用的是python的exec,大家可以好好看看exec函数的使用方法即可理解ipyhton的编程思路:

async def run_code(self, code_obj, result=None, *, async_=False):
        """Execute a code object.

        When an exception occurs, self.showtraceback() is called to display a
        traceback.

        Parameters
        ----------
        code_obj : code object
          A compiled code object, to be executed
        result : ExecutionResult, optional
          An object to store exceptions that occur during execution.
        async_ :  Bool (Experimental)
          Attempt to run top-level asynchronous code in a default loop.

        Returns
        -------
        False : successful execution.
        True : an error occurred.
        """
        # Set our own excepthook in case the user code tries to call it
        # directly, so that the IPython crash handler doesn't get triggered
        old_excepthook, sys.excepthook = sys.excepthook, self.excepthook

        # we save the original sys.excepthook in the instance, in case config
        # code (such as magics) needs access to it.
        self.sys_excepthook = old_excepthook
        outflag = True  # happens in more places, so it's easier as default
        try:
            try:
                self.hooks.pre_run_code_hook()
                if async_ and sys.version_info < (3,8):
                    last_expr = (await self._async_exec(code_obj, self.user_ns))
                    code = compile('last_expr', 'fake', "single")
                    exec(code, {'last_expr': last_expr})
                elif async_ :
                    await eval(code_obj, self.user_global_ns, self.user_ns)
                else:
                    exec(code_obj, self.user_global_ns, self.user_ns)
            finally:
                # Reset our crash handler in place
                sys.excepthook = old_excepthook
        except SystemExit as e:
            if result is not None:
                result.error_in_exec = e
            self.showtraceback(exception_only=True)
            warn("To exit: use 'exit', 'quit', or Ctrl-D.", stacklevel=1)
        except self.custom_exceptions:
            etype, value, tb = sys.exc_info()
            if result is not None:
                result.error_in_exec = value
            self.CustomTB(etype, value, tb)
        except:
            if result is not None:
                result.error_in_exec = sys.exc_info()[1]
            self.showtraceback(running_compiled_code=True)
        else:
            outflag = False
        return outflag

    # For backwards compatibility
    runcode = run_code

希望能够早点能够完成这个插件,不过明天又有其他任务,先耽搁一下。


在上周的时候,发现了其实jupyter在网页上做代码编写调试等这些,其是是非常不方便的,比如没有智能提示这些功能。

然后周一的时候就想倒腾一个vscode的插件,当时就查看了上面的ipython的源码。

然后万能的百度告诉我,其实不用我来折腾这个插件了,虽然效果没有我想的那么好,但是勉强还是能够用的。VSCode 编写 Python 支持 Jupyter notebook 了!

先用着,期待这个插件的后续更新。


其实还有个东西,可以了解下,在node中执行python脚本,Node.js 与 Python 混合编程。

前者使用的新起一个进程,后者就是使用的nodejs 中的 python-shell来做的python调用,感觉后者封装要好一点。