IPython,让Python显得友好十倍的外套——windows XP/Win7安装详解

IPython,让Python显得友好十倍的外套——windows XP/Win7安装详解

前言

学习python,官方版本其实足够了。但是如果追求更好的开发体验,耐得住不厌其烦地折腾。那么我可以负责任的告诉你:IPython是我认为的唯一显著好于原版python的工具。

整理了《Python 二三事》:http://pre-sence.com/archives/python-intro   《Python 四五事》:http://pre-sence.com/archives/python-misc 并加入安装IPython部分。

写这篇随笔的原因是:忽然醒悟之前我安装IPython折腾许久不成功可能是我未能想起pip或easy_install这两个python的上帝工具。参考:Python包管理工具pip与easy_install

个人经验总结:IPython,是学习python的利器,是让Python显得友好十倍的外套,是我唯一的强烈推荐。

安装IPython

任何Linux发行版对编程者都十分友好

Ubuntu为例: sudo apt-get install ipython

windows环境:

1、下载ez_setup.py,右击左边链接,另存为,使用python ez_setup.py运行,或直接双击。

2、步骤1成功后,cmd下输入命令easy_install -h可以测试,正常反应说明已经可以使用easy_install了。

3、cmd下输入easy_install pip安装pip,这是因为pip正是easy_install的下一代,比easy_install好用。

4、步骤3成功后,pip install ipython。

5、如果步骤4不行,退一步,使用easy_install ipython安装。

运行IPython

cmd提示符下,输入ipython运行就可以使用除了原python外,IPython多出来的贴心的“I”了。

退出IPython

与python一样也是输入exit

Python实用技巧:

1、关于 "_" 字符使用

在 Python shell 下 _ 总是被赋予之前最后一个表达式的值(注:@pythonwood)。这里看个例子应该就能清楚:

>>>importstring

>>> string.letters

'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'

>>>print_

abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ

>>>2014

2014

>>> v=_

>>> v

2014

举个实际的例子,比如你在调试时读文件的时候直接进行 f.read() ,你看了看发现输出结果很有意思,想要对它进行进一步处理,但发现读的时候忘记赋值了。以往你只能叹叹气重新开文件再读一次,现在你只要执行 result = _,把 _ 附到另外一个变量就可以了。

2、python -m

相信很多人应该用过这个东西,Python 很多标准库都提供这样的调用方式来实现一些简单的命令行功能。Python 3 现在自带 pip。比如我们想使用 Python 3 的 pip 来安装别的库,我们可以这样:

py -3 -m pip install bottle

跟你预料的一样,这样就可以了。当然你可以用个 .bat 文件来把这些包裹起来并放在 Path 上,一个简单的例子,把下面的内容写到一个叫 pip3.bat 的文件里:

@echo off

py -3 -m pip %*

并放到 Path 上,就可以方便调用了。其中 %* 负责传递所有的命令行参数。

实际上 python -m 可以用的东西还真的挺多,这里给出一个不完全的列表:

######################################################

# 最强功能

######################################################

# 局域网共享,宿舍中任意一台笔记本都可以瞬间变身web资源共享服务器

# 命令ipconfig可以看到局域网ip地址,一般是192,172这些开头的。

# 使用本机80端口,可任意设置。只共享当前运行目录。

#

python-m SimpleHTTPServer80

#

# 本机任意浏览器输入http://localhosthttp://127.0.0.1可以访问。

# (80端口浏览器默认的,不需输入)甚至在地址栏直接输入localhost即可。

# 局域网,(宿舍)任意电脑输入上面所说192或172等开头的IP地址即可访问。

######################################################

# 缩进输出 JSON

echo {"hey":"kid"} | python-m json.tool

# 简单的执行时间测量

python-m timeit [ix*ixforixinrange(100)]

# 简单的 Profiling

python-m cProfile myscript.py

# 比较两个文件夹的区别

python-m filecmp path/to/a path/to/b

# base64 转换

echo foo bar | python-m base64

# 调用默认浏览器打开一个新标签页

python-m webbrowser-t http://google.com

# 生成程序文档

python-m pydoc myscript.py

# 类似 nose 的自动搜索 unittest

python-m unittest discover

# 调用 pdb 执行代码

python-m pdb myscript.py

IPython实用技巧:

1、Tab自动补全,一种是简单的关键字补全,另外一种是对象的方法和属性补全。

作为例子,我们先引入sys模块,之后再输入sys.(注意有个点),此时按下 tab 键,IPython 会列出所有 sys 模块下的方法和属性。

接着上面的例子,我们输入sys?,这样会显示出sys模块的 docstring及相关信息。很多时候这个也是很方便的功能。

2、IPython 还有强大之处很大部分还体现在它的magic function中。它是指的在 IPython 环境下执行以%开头的一些命令来对 IPython 进行一些设定或者执行某些功能。在 IPython 中输入%lsmagic就能列出所有的magic functions。在这里简单介绍下几个比较有意思的,你也可以自己通过查看文档来找找有哪些你特别用的到得。

之前看到能用?来查询函数的文档,对于 magic function 也是如此。比如%run?。

!cd ..在命令前面加上!则它会被作为命令行命令执行,这样你就不用退出 IPython 来进行命令行操作。

%run foo.py在当前环境下直接执行foo.py,效果跟命令行下调用ipython foo.py相同。

%time foo.bar()跟timeit decorator作用相同,进行简单的 profile。

%hist能显示之前输入过的命令的历史,同时你可以用In[]来访问之前的命令。比如%exec In[10]就能执行列表中第十行。

%rep类似上面的_变量,但是是以字串的形式返回

最后,如果%automagic是打开的状态的话,所有 magic function 不需要在前面加%就能正确调用。

在当前 IPython 版本中还有一个由于安全原因没有默认引入的%autoreload,它的作用是在可以自动重新载入你调用的函数,以及其相关模块。接触过django的同学对这个应该比较熟悉,在 IPython 中的效果就是,当你在调试一个一直在反复改动的函数时,你可以开启这个功能保证每次调用都会重新读取最新的版本,让你在源码中的改动马上生效。在 IPython 中执行

importipy_autoreload

%%autoreload2

这样 IPython 会对所有的模块都进行 autoreload。你可以通过执行%autoreload?来查询它的文档来进行进一步设定。如果你希望 IPython 每次启动自动载入次功能,那么可以通过配置 ipythonrc (在 Windows 下可以在C:\Users\\_ipython\ipythonrc.ini找到) 来进行相关设置。

3、还有一个很神奇的功能。如果你的程序是由命令行开始执行的,即在命令行下输入python foo.py(大部分 Python 程序都是),那么你还可以利用 IPython 在你的程序任意地方进行断点调试!

在你程序中任意地方,加入如下语句:

fromIPython.ShellimportIPShellEmbed

IPShellEmbed([])()

注意:最近 IPython 发布了0.11 版本,各方面变化都非常大,API 也经过了重新设计。如果你使用的是 0.11 那么上面两行对应的是这样的:

fromIPythonimportembed

embed()

再和平常一样运行你的程序,你会发现在程序运行到插入语句的地方时,会转到 IPython 环境下。你可以试试运行些指令,就会发现此刻 IPython 的环境就是在程序的那个位置。你可以逐个浏览当前状态下的各个变量,调用各种函数,输出你感兴趣的值来帮助调试。之后你可以照常退出 IPython,然后程序会继续运行下去,自然地你在当时 IPython 下执行的语句也会对程序接下来的运行造成影响。

这个方法我实在这里看 到的。想象一下,这样做就像让高速运转的程序暂停下来,你再对运行中的程序进行检查和修改,之后再让他继续运行下去。这里举一个例子,比如编写网页 bot ,你在每取回一个页面后你都得看看它的内容,再尝试如何处理他获得下一个页面的地址。运用这个技巧,你可以在取回页面后让程序中断,再那里实验各种处理方 法,在找到正确的处理方式后写回到你的代码中,再进行下一步。这种工作流程只有像 Python 这种动态语言才可以做到。

4、一个实际的例子

这里以一个简单的例子来讲解一下是怎样的一个情况。我们要写一个可以将简单的数据表达式,类似1 + (2 - 3) * 456解析成树的Pratt Parser。首先我们需要一个 lexer 把每个 token 解析出来,那么最开始的代码就是:

# simple math expression parser

deflexer(s):

'''token generator, yields a list of tokens'''

yields

if__name__=='__main__':

fortokeninlexer("1 + (2 - 3) * 456"):

printtoken

明显这个没有任何意义,但现在程序已经有足够的东西能够跑起来。我们把这个程序存为expr.py,开启一个命令行窗口,运行ipython然后像这样执行它:

$ ipython

IPython0.13.1--An enhanced Interactive Python.

?-> Introductionandoverview of IPython's features.

...

In [1]: run expr.py

1+(2-3)*456

在 IPython 里面用run跑的好处有很多,首先是你在程序执行完毕后整个程序的状态,比如最后全局变量的值,你写的函数这些你都是可以随便执行的!同样的你可以在 IPython 里面保存一些用来测试的常量,每次用run跑的话新的程序会被重新载入,你可以这样方便的测试每个函数,有一个非常动态的环境来调试你的程序:

In [2]:printtoken# 注意这里 token 就是 __main__ 里面的那个 token 的值

1+(2-3)*456

In [3]:printlist(lexer('1+2+3'))# 可以运行你写的函数

['1+2+3']

然后按照之前的想法,我们尝试把这个 lexer 写出来。在这个过程中,IPython 可以用来查看函数的文档,测试如何调用某些函数,看看返回值是什么样子等等,还是跟上面的说的一样,我们有一个动态的环境可以真真正正的执行程序,你可以 在把代码写到你珍贵的主程序之前就有机会运行它,这样你可以更确认你的代码能正常工作:

In [4]: s="foo"# 忘记判断字符串是数字的函数的名字了,用一个字符串试试看

In [5]: s.is# 开头大概是 is,这里按下 tab 键 IPython 会帮我们补全

s.isalnum  s.isalpha  s.isdigit  s.islower  s.isspace  s.istitle

In [6]: s.isdigit?# 结果是 isdigit,在表达式后加上问号并回车查看文档

Type:       builtin_function_or_method

String Form:

Docstring:

S.isdigit()->bool

ReturnTrueifallcharactersinS are digits

andthereisat least one characterinS,Falseotherwise.

In [8]: s.isdigit()# 调用试试看

Out[8]:False

In [9]:'f'in'foo'# 试试字符串能不能用 in 来判断

Out[9]:True

确认了各个步骤以后,我们把 lexer 的代码填起来。我们为了节省纵向的空间我们把很多东西写在一行里面:

# simple math expression parser (broken lexer)

deflexer(s):

'''token generator'''

ix=0

whileix

ifs[ix].isspace(): ix+=1

ifs[ix]in"+-*/()":

yields[ix]; ix+=1

ifs[ix].isdigit():

jx=ix+1

whilejx

yields[ix:jx]; ix=jx

else:

raiseException("invalid char at %d: '%s'"%(ix, s[ix]))

yield""

if__name__=='__main__':

printlist(lexer("1 + (2 - 3) * 456"))

看起来不错,我们还是在 IPython 里执行试试,结果发现程序抛出了一个异常:

In [6]: run expr.py

------------------------------------------------------------------

Exception                       Traceback (most recent call last)

py/expr.pyin()

if__name__=='__main__':

--->20printlist(lexer("1 + (2 - 3) * 456"))

py/expr.pyinlexer(s)

yields[ix:jx]; ix=jx

else:

--->raiseException("invalid character at ...))

yield""

Exception: invalid character at3:' '

嗯?好像程序里已经处理了空格的情况。怎么会这样?不知道你碰到异常的时候一般都怎么办。你可能会选择到处添加print,用 IDE 断点调试。其实这种情况用pdb是很明智的选择,在 IPython 里我们可以非常轻松的使用它。

In [13]: pdb# 开启 pdb ,这样在异常的时候我们会自动的 break 到异常处

Automatic pdb calling has been turned ON

In [14]: run expr.py

-----------------------------------------------------------------

Exception: invalid character at3:' '

> py/expr.py(15)lexer()

else:

--->raiseException("invalid char at ...))

yield""

ipdb>printix# 这里我们可以执行任何 Python 的代码


ipdb> whatis ix# 也可以用 pdb 提供的命令,输入 help 可以查看所有命令

通过方便的调试和仔细检查代码,我们发现是没有正确的使用elif造成了问题!(我知道这个过程不是太符合情理...)。把代码里的后面的几个if都换成elif以后我们发现结果基本上是对的了。我们可以马上再跑几个类似的例子,确认不同的输入是否都有比较好的结果:

In [18]: run expr.py# 这次差不多对了,我们可以试试几个别的例子

['1','+','(','2','-','3',')','*','456', '']

In [19]:printlist(lexer("1*123*87-2*5"))

['1','*','123','*','87','-','2','*','5', '']

# 跟在 shell 里面一样,你可以用上下来选取之前的记录,然后简单的修改再重新执行。

# 记得每次 run 后你的函数都是最新版本,你可以很简单的用重复的数据来测试你的函数

# IPython 甚至还实现了 Ctrl+R!自己试试看吧

In [19]:printlist(lexer("1 + two"))

Exception: invalid character at2:'t'...

在一段痛苦的调试之后,我们最终把程序写出来了。很遗憾程序超出了我预计的长度,就不贴在这里了。后面部分的开发过程跟前面基本还是一样,总结起来就是:

保持你的程序是一个可以运行并且有意义的状态,尽可能频繁的运行。

在 IPython 里查看文档,尝试小的程序片段,测试些你不确定的做法,确定之后再把东西添加到你的代码里。

用不同的参数在 IPython 里测试你正在编写的函数/class。

当遇到问题的时候,先简单的用pdb在异常处 break,十有八九都能有些头绪。

额外的注意事项

这里举的例子是你所有的开发都是在单个.py文件里的。现实生活中你很有可能会横跨几个文件一起修改。请务必注意,在 IPython 里你每次run的时候只有被run的那个文件里的东西会是最后修改的版本,其import的东西如果在期间被修改是不会反应出来的。

这个的原理就跟你在 Python shell 里在修改前修改后重复import某个模块不会有作用是一样的,Python 神奇的import机制不会去追踪其他模块的修改。你可以手动用reload函数来重新载入,你也可以使用 IPython 的autoreload功能来让你忽略这个问题。个人来说我没怎么用过这个功能,IPython 没有默认开启它可能也是有些顾虑,请自己评估看看。

另外你应该已经注意到,run的效果基本上就是把你的代码拷贝进 IPython 里执行一遍。对于没有__main__的文件,你也可以run,这样里面定义的函数和 class 就会反映出你的更改。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,948评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,371评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,490评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,521评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,627评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,842评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,997评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,741评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,203评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,534评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,673评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,339评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,955评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,770评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,000评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,394评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,562评论 2 349

推荐阅读更多精彩内容