零基础学编程023:用with实现优雅地释放资源

在《零基础学编程022:函数的世界》中我们写了一个函数,通过访问新浪的实时行情服务,得到股票的开盘价。

import urllib.request as req

def price(stock) :
    url = 'http://hq.sinajs.cn/list=' + stock
    with req.urlopen(url) as f :
        hq = f.read().decode('GBK')
        v = hq.split(',')
        return v[1]

新手对 with 的用法不太理解,如果以前学过C#语言,这个with类似于using关键词。先来看看不太好的写法吧:

import urllib.request as req

def price(stock) :
    url = 'http://hq.sinajs.cn/list=' + stock
    f = req.urlopen(url)   # 尽量不要用这种写法!
    hq = f.read().decode('GBK')
    v = hq.split(',')
    f.close() # 当前面发生异常时,不一定能够执行到这条语句
    return v[1]

上面这段代码没有用 with ... as ... 的写法,而是用赋值语句把req.urlopen(url)赋给了 f,在返回开盘价 return v[1] 之前调用了 f.close() 把网络连接关闭。

在绝大多数情况下,这种代码不会有什么问题。但这里的代码访问了网络,而访问网络会有各种异常情况,比如网卡被禁用、WIFI未连接、无法连接互联网、网络地址无效、代理设置不正确、网络服务器故障、防火墙阻挡等等,这些异常都是编程之前无法完全预料的。

我们调用 urlopen() 打开了一个网络连接,在最后务必要保证把它关闭,即调用close() 函数。但当网络已经发生异常了,此时还未执行到close() 函数,程序就已经异常退出了,所以网络连接可能仍处于打开状态。

一般的小程序,这少量的未关闭的网络连接并不会造成什么麻烦,有时操作系统还会在进程关闭时自动释放这些连接,但如果编写服务端程序时,几秒钟之内就可能产生数千个并发连接,当这种问题积累到一定程度后,程序就会出现莫名其妙的错误,而且这种错误特别难定位。

我在2002年用java写过一个网络信息发布系统,当时有人的代码里没有正确地释放Oracle数据库连接,当正式上线时,几分钟之内产生了数百个未释放的数据库连接,Oralce主数据库差点宕掉,幸好我们及时地把程序摘掉,才避免了一次事故的发生。

所以学习编程时,一定要参考别人的例子代码,尤其是参考官方的例子代码。网上流传的一些核心代码只是为了说明具体的用法,写法上并不规范,也没有加入异常处理的相关代码,而真正产品级的代码,会加上许多边界条件检查、异常判断的语句,从而让产品更加健壮。

小结:

  • with 语句用于保证一些资源(文件、网络连接、数据库等)在发生异常时能够正常地关闭或释放
  • 编程初期就养成良好地编程习惯,将错误扼杀在摇篮里
  • with 语句内部会自动调用close()语句释放网络连接,其背后还有比较复杂的实现机制,以后再说

--- END ---

原文发布于微信公众号 - 申龙斌的程序人生(slbGTD)

原文发表时间:2017-02-21

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏Ceph对象存储方案

RGW Bucket Shard设计与优化-上

1 bucket index背景简介 bucket index是整个RGW里面一个非常关键的数据结构,用于存储bucket的索引数据,默认情况下单个bucke...

1.5K50
来自专栏云之翼

在虚拟机上容器环境性能--动态测试问题分析总结(二)

在上一篇中,介绍了静态测试场景,本文介绍动态性能测试的差异分析,希望大家可以借鉴。

16400
来自专栏七夜安全博客

go go go - beego

在上一篇文章What!!! so fast中,我介绍了golang这种语言,并使用golang开发了一个端口扫描工具。现在我的主要工作是做网络安全方面的开发与策...

41220
来自专栏向治洪

android mtp简介

经作者同意,转发我们公司MTP专家同事huirong的一篇文章。大家也可在程序员第5期看到。 MTP in Android MTP的全称是Media Tra...

49060
来自专栏编程

教你从零开始搭建一款前端脚手架工具

本文系原创,转载请注明:作者:Jrain Lau(https://segmentfault.com/u/jrainlau)项目地址:https://github...

55370
来自专栏用户画像

IDEA Facets与Artifacts

Facets表述了在Module中使用的各种各样的框架、技术和语言。这些Facets让Intellij IDEA知道怎么对待module内容,并保证与相应的框架...

38010
来自专栏积累沉淀

Javascript模块化编程(二):AMD规范

这个系列的第一部分介绍了Javascript模块的基本写法,今天介绍如何规范地使用模块。 (接上文) 七、模块的规范 先想一想,为什么模块很重要? 因...

39780
来自专栏蓝天

apache thrift的不足

thrift作为RPC优点明显,那些还在坚持使用消息排斥RPC的同学,都应当亲自接触体验一下。 

11510
来自专栏北京马哥教育

Linux 软中断机制分析

软中断分析最近工作繁忙,没有时间总结内核相关的一些东西。上次更新博客到了linux内核中断子系统。这次总结一下软中断,也就是softirq。之后还会总结一些ta...

62880
来自专栏CSDN技术头条

调试大规模服务器集群的五大策略

随着互联网迅速发展,用户访问量以及服务器规模的越来越大,因此,创建一个可靠、稳定、优质的互联网服务是开发者的首要目标。而对于开发者而言,是否具备一个完善的服务器...

28490

扫码关注云+社区

领取腾讯云代金券