【导语】:ipython 是一个 python的交互式shell,比默认的 python shell好用得多。它有许多好用的特性,本文将对一些特性进行介绍。
介绍
ipython 是一个python的交互式shell,比默认的 python shell好用得多,支持变量自动补全,自动缩进,内置了许多很有用的功能和函数。在之前的项目中,我使用 ipython 较多,每当在开发中遇到问题时,我会打印每一步的输出,查找问题。完成项目后,我对之前使用 ipython 的一些经验作了总结。在本文,我将对之前的总结作以简单介绍。
此外,文中的部分命令配有 gif 图演示,但由于比较大,没法上传到微信公众号。如果有需要 gif 演示动图的小伙伴,请看文末获取方式。
1. 显示文档
in [1]: import rein [2]: re.findall?signature: re.findall(pattern, string, flags=0)docstring:return a list of all non-overlapping matches in the string.if one or more capturing groups are present in the pattern, returna list of groups; this will be a list of tuples if the patternhas more than one group.empty matches are included in the result.file: ~/.pyenv/versions/3.9.0/lib/python3.9/re.pytype: function
这是我最喜欢的功能之一。我们可以通过在任何函数、模块、变量的开头或结尾添加“?”来显示其文档。它被称为“动态对象检查”,通过使用该特性,我们就可以在不退出终端的情况下来获取文档。在标准的python交互式解释器中repl中,使用help()函数也能获取文档信息,但?输出的文档可读性更强。它能将函数签名对象signature、文档字符串等重要信息高亮显示。(由于我使用的语法高亮库不支持ipython,因此在这里无法显示)
2. 显示源代码
in [1]: import pandasin [2]: pandas.dataframeinit signature:pandas.dataframe( data=none, index: optional[collection] = none, columns: optional[collection] = none, dtype: union[forwardref('extensiondtype'), str, numpy.dtype, type[union[str, float, int, complex, bool]], nonetype] = none, copy: bool = false,)source:class dataframe(ndframe): two-dimensional, size-mutable, potentially heterogeneous tabular data. data structure also contains labeled axes (rows and columns). arithmetic operations align on both row and column labels. can be thought of as a dict-like container for series objects. the primary pandas data structure. parameters ----------
假如我们想查看一个函数(或者类/模块)的源代码,可以使用两个问号,例如:function_name,function_name。
3. %edit 函数
3_edit.gif
如果我们想在 ipython 中写一个功能较复杂的函数,可以使用 %edit 命令打开自己喜欢的编辑器(也可以用 $editor环境变量设置编辑器),在里面编写代码。当我们保存并关闭这个文件时,ipython 就会自动执行该文件。
我通常将它与vim编辑器结合使用,这样就不需要切换到代码编辑器了,当编写稍微长一点的函数时,效果很好。但是,如果函数体的代码过多,那么直接在 ipython中编写就比较麻烦了。
4. 使用%edit -p打开之前的文件
4_edit_p.gif
假如我们想修改上次编写的代码,可以使用%edit -p重新打开文件。
5. 通配符搜索
in [1]: import osin [2]: os.*dir*?os.__dir__os.chdiros.curdiros.fchdiros.listdiros.makedirsos.mkdiros.pardiros.removedirsos.rmdiros.scandiros.supports_dir_fdin [3]: os.chdir(/some/other/dir)
如果我们忘记了某个函数的名称,可以使用动态对象检查(“?”)和通配符(“*”)进行搜索。例如,我们知道os模块有一个可以改变当前目录的方法,但是忘记了该方法的具体名称。可以列出os模块中的所有函数,由于关于文件操作的函数名称中包含“dir”。因此,可以搜索os模块中名称包含“dir”的所有函数。
6. %debug
假如程序出现了异常,我们可以使用%debug命令开启调试。无需打断点,或者使用特殊的参数运行 ipython。
in [1]: from solver import solvein [2]: solve()indexerror: list index out of rangein [3]: %debug> /users/switowski/workspace/iac/solver.py(11)count_trees() 9 x = (x + dx) % mod 10 y += dy---> 11 if values[y][x] == #: 12 count += 1 13 return countipdb>
7. 自动开启调试
如果我们希望异常出现时,调试器自动启动,可以使用%pdb命令,再次使用该命令会关闭该功能。
in [1]: %pdbautomatic pdb calling has been turned onin [2]: from solver import solvein [3]: solve()indexerror: list index out of range> /users/switowski/workspace/iac/solver.py(11)count_trees() 9 x = (x + dx) % mod 10 y += dy---> 11 if values[y][x] == #: 12 count += 1 13 return countipdb> y1ipdb> x3ipdb>
8. shell命令
如果想在 ipython 中使用shell命令,可以在命令前加上感叹号。像ls, pwd, cd这种常用shell命令,也可以不加感叹号。我主要使用shell命令来移动文件,或者在文件夹间移动。我们还可以在ipython中为另一种编程语言开启repl。
in [1]: !pwd/users/switowski/workspace/iacin [2]: ls -altotal 8drwxr-xr-x 5 switowski staff 480 dec 21 17:26 ./drwxr-xr-x 55 switowski staff 1760 dec 22 14:47 ../drwxr-xr-x 9 switowski staff 384 dec 21 17:27 .git/drwxr-xr-x 4 switowski staff 160 jan 25 11:39 __pycache__/-rw-r--r-- 1 switowski staff 344 dec 21 17:26 solver.py# node repl inside ipython? sure!in [3]: !nodewelcome to node.js v12.8.0.type .help for more information.> var x = hello worldundefined> x'hello world'>
9. 使用%cd命令在文件系统间移动
我们可以使用%cd命令在文件系统中移动(按tab键可以自动补全文件夹路径)。此外,还可以收藏一个文件夹或将一些文件夹移回历史记录(运行%cd?查看该命令的具体信息)。
in [1]: !pwd/users/switowski/workspace/iac/input_files/wrong/folderin [2]: %cd ../../users/switowski/workspace/iac/input_filesin [3]: %cd right_folder//users/switowski/workspace/iac/input_files/right_folder
10. %autoreload
使用%autoreload命令可以在运行导入的函数前,重载该函数。当我们在 python 中导入一个函数时,python 会将其源代码保存在内存中(实际上,真实的情况比较复杂)。当我们更改了函数,python 不会重新加载函数,而是继续使用之前的代码。
如果我们想创建一个函数或模块,并且希望在不重启 ipython 的情况下测试代码(可以使用importlib.reload()),就可以使用%autoreload。通过使用该命令,就可以实现重载函数的效果。如果你想了解更多信息,可以查看这篇文章[1]。
10_autoreload.gif
11. 用%xmode展示详细的异常信息
默认情况下,ipython 抛出的异常信息量足够查找错误——至少对我来说是这样。但是,如果你想展示详细的异常信息,可以使用%xmode命令。它可以用四种形式展示异常信息,开发者按需选择。
minimal
in [1]: %xmodeexception reporting mode: minimalin [2]: solve()indexerror: list index out of range
plain
in [3]: %xmodeexception reporting mode: plainin [4]: solve()traceback (most recent call last): file , line 1, in solve() file /users/switowski/workspace/iac/solver.py, line 27, in solve sol_part1 = part1(vals) file /users/switowski/workspace/iac/solver.py, line 16, in part1 return count_trees(vals, 3, 1) file /users/switowski/workspace/iac/solver.py, line 11, in count_trees if vals[y][x] == #:indexerror: list index out of range
context(默认设置)
in [5]: %xmodeexception reporting mode: contextin [6]: solve()---------------------------------------------------------------------------indexerror traceback (most recent call last) in ----> 1 solve()~/workspace/iac/solver.py in solve() 25 def solve(): 26 vals = getinput()---> 27 sol_part1 = part1(vals) 28 print(fpart 1: {sol_part1}) 29 print(fpart 2: {part2(vals, sol_part1)})~/workspace/iac/solver.py in part1(vals) 14 15 def part1(vals: list) -> int:---> 16 return count_trees(vals, 3, 1) 17 18 def part2(vals: list, sol_part1: int) -> int:~/workspace/iac/solver.py in count_trees(vals, dx, dy) 9 x = (x + dx) % mod 10 y += dy---> 11 if vals[y][x] == #: 12 cnt += 1 13 return cntindexerror: list index out of range
verbose (与context类似,但其中包含局部变量和全局变量)
in [7]: %xmodeexception reporting mode: verbosein [8]: solve()---------------------------------------------------------------------------indexerror traceback (most recent call last) in ----> 1 solve() global solve = ~/workspace/iac/solver.py in solve() 25 def solve(): 26 values = read_input()---> 27 part1 = solve1(values) part1 = undefined global solve1 = values = [['..##.......', ..., '.#..#...#.#']] 28 print(fpart 1: {part1}) 29 print(fpart 2: {solve2(values, part1)})~/workspace/iac/solver.py in solve1(values=[['..##.......', ..., '.#..#...#.#']]) 14 15 def solve1(values: list) -> int:---> 16 return count_trees(values, 3, 1) global count_trees = values = [['..##.......', ..., '.#..#...#.#']] 17 18 def solve2(values: list, sol_part1: int) -> int:... and so onindexerror: list index out of range
12. rerun 命令
可以使用%rerun ~1/重新运行前一个会话中的所有命令。但该命令有一个很大的缺点——如果之前的会话中有任何异常,执行就会停止。因此,必须手动删除有异常的命令行。如果你正在使用jupyter notebook,可以将出现异常的地方标记为“raising an exception”。如果使用rerun 命令,ipython 将忽略此异常。这不是一个完美的解决方案,假如可以在%rerun命令设置,效果会更好。
in [1]: a = 10in [2]: b = a + 20in [3]: bout[3]: 30# restart ipythonin [1]: %rerun ~1/=== executing: ===a = 10b = a + 20b=== output: ===out[1]: 30in [2]: bout[2]: 30
13. 在启动 ipython 时运行某些代码
如果你想在每次启动 ipython 时执行一些代码,只需在“startup”文件夹(~/.ipython /profile_default/startup/)中创建一个新文件,并在其中书写代码。ipython将自动执行该文件。你也可以在该文件中导入一些模块,但如果文件中的代码过多,将会影响ipython的启动速度。
13_startup.gif
14. 使用不同的配置文件
如果我们想导入一些模块,并配置某些东西。例如在调试/分析时,我们想让输出的异常信息为verbose模式,并导入一些分析库。此时不能将其放入默认配置文件中,因为我们无需对每个文件都进行调试或分析。我们可以创建一个新的配置文件。配置文件就像ipython的不同用户帐户——每个帐户都有自己的配置文件和启动文件夹。
14_profile.gif
15. 保存表达式结果
如果你忘记了将表达式赋值给变量,可以使用var = _. _存储最后一个命令的输出(这在python repl中也适用)。这样前面所有命令的结果都存储在了:变量_1(第一个命令的输出),_2(第二个命令的输出),依次类推。
in [1]: sum(range(1000000))out[1]: 499999500000in [2]: the_sum = _in [3]: the_sumout[3]: 499999500000in [4]: _1out[4]: 499999500000
16. 编辑任何函数或模块
你可以使用%edit编辑任何python函数,包括:自定义的函数,用pip安装的第三方库中的函数,甚至是内置的函数。甚至不需要知道函数位于哪个文件中,只需指定函数名称(必须先导入它),ipython 就会自动找到它。在下面的例子中,我修改了内置的randint()函数,让它始终返回42。
16_edit.gif
17. 分享代码
如果你想把代码分享给其他人,可以使用%pastebin命令,并指定共享的代码。ipython 将创建一个pastebin(类似于github 的 gist),粘贴选定的行,并返回一个链接,你可以把它发送给别人。务必记住,这个链接会在7天后过期。
in [1]: welcome = welcome to my gistin [2]: welcomeout[2]: 'welcome to my gist'in [3]: a = 42in [4]: b = 41in [5]: a - bout[5]: 1in [6]: %pastebin 1-5out[6]: 'http://dpaste.com/8qa86f776'
18. 将 ipython 作为debugger
我们还可以把 ipython 当作debugger使用。ipython自带“ipdb”——它类似于内置的python调试器“pdb”,但其中有一些ipython的特有特性(语法高亮显示、自动补全等)。通过设置pythonbreakpoint环境变量,调用breakpoint(),就可以在断点语句中使用ipdb了。但需要在 python 3.7或更高版本中使用(python3.7之后才引入了breakpoint()语句)。18_debugger.gif
19. 执行用其他语言编写的代码
假设我们想要在不退出 ipython 的情况下,执行用另一种语言编写的一些代码。比如输入%%ruby,再编写一些ruby代码,然后按两次enter键,ipython就会运行这段代码。ipython 支持ruby、bash或javascript等语言。它也适用于python2 (%%python2)。
in [1]: %%ruby ...: 1.upto 16 do |i| ...: out = ...: out += fizz if i % 3 == 0 ...: out += buzz if i % 5 == 0 ...: puts out.empty? ? i : out ...: end ...: ...:12fizz4buzzfizz78fizzbuzz11fizz1314fizzbuzz16
20. 在会话中存储变量
ipython使用sqlite来存储之前的会话。我们也可以用它来存储自定义的数据。例如,使用%store命令,就可以在ipython的数据库中保存变量,使用estore -r可以另一个会话中恢复它们。您还可以在配置文件中设置c.storemagics.autorestore = true,以便在启动ipython时自动从数据库恢复所有变量。
in [1]: a = 100in [2]: %store astored 'a' (int)# restart ipythonin [1]: %store -r ain [2]: aout[2]: 100
21. 将会话保存进一个文件
我们可以使用%save命令将ipython会话保存到一个文件中,然后对代码进行修改,无需手动复制粘贴到代码编辑器中。
in [1]: a = 100in [2]: b = 200in [3]: c = a + bin [4]: cout[4]: 300in [5]: %save filename.py 1-4the following commands were written to file `filename.py`:a = 100b = 200c = a + bc
22. 清理>标记或者不正确的缩进
如果我们想清除不正确的缩进或“>”符号(例如,从git diff、文档字符串或电子邮件中复制的代码,都含有冗余信息),无需手动操作,可以复制代码并运行%paste。ipython将从剪贴板粘贴代码,修复缩进,并删除“>”符号(尽管它有时不能正常工作)。
# clipboard content:# >def greet(name):# > print(fhello {name})# just pasting the code won't workin [1]: >def greet(name): ...: > print(fhello {name}) file , line 1 >def greet(name): ^syntaxerror: invalid syntax# but using %paste worksin [2]: %paste>def greet(name):> print(fhello {name})## -- end pasted text --in [3]: greet(sebastian)hello sebastian
23. 列出所有变量
使用%whos命令可以显示出当前会话的所有变量,包括变量类型和存储的数据。
in [1]: a = 100in [2]: name = sebastianin [3]: squares = [x*x for x in range(100)]in [4]: squares_sum = sum(squares)in [5]: def say_hello(): ...: print(hello!) ...:in [6]: %whosvariable type data/info-----------------------------------a int 100name str sebastiansay_hello function squares list n=100squares_sum int 328350
24. 使用异步函数
可以使用异步函数提高代码的运行速度。要使用异步,必须先启动一个事件循环来调用它们。方便的是,ipython自带事件循环!这样,无需额外操作就能使用异步函数了。
in [1]: import asyncioin [2]: async def worker(): ...: print(hi) ...: await asyncio.sleep(2) ...: print(bye) ...:# the following code would fail in the standard python repl# because we can't call await outside of an async functionin [3]: await asyncio.gather(worker(), worker(), worker())hihihibyebyebye
25. ipython 脚本
我们可以在命令前加上!或者&,执行包含 ipython 特定语法的文件,这种文件的扩展名为“ipy”。
$ lsfile1.py file2.py file3.py file4.py wishes.ipy$ cat wishes.ipyfiles = !ls# suffix 运行所有后缀为.py的文件for file in files: if file.endswith(.py): %run $file$ ipython wishes.ipyhave avery merrychristmas!
结论
ipython 是我最喜欢的 python 工具之一。它有许多好用的特性,本文分享了一些,如果你知道其他特性,可以留言分享!
OLED和量子点终究还是败给了LCD
增强现实的发展卡在哪里了
新基建给智能化行业带来了哪些机遇
汽车排放污染检验中新车排放标准的发展及赶超历程
华为三大基石加速商用之路
IPython的特性介绍及使用技巧
使用人工智能实现天基ISR的PreVAIL系统
关于ARM核异常与中断处理机制研究
多功能食品安全检测仪器的特点
安全是未来汽车发展的关键所在
Pico W的无线功能
小米华为手机行业里的巨头为何坚持要做笔记本呢?
FTP的主动模式和被动模式
华为轮值董事长胡厚崑表示我们的芯片战略没有做出任何改变
NVIDIA 在 Microsoft Azure 上推出面向全球企业和初创公司的生成式 AI Foundry 服务
MS1100 完美替代ADS1100
芯盾时代中标广州农商银行 如期完成国密改造提升自主可控能力
射频功率放大器的基础知识
谷景教你如何正确选择功率贴片电感厂家
2019年的无线通信技术都有哪些发展趋势