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调用,感觉后者封装要好一点。