社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Python

Python中一条高端、大气、上档次的语句

Python网络爬虫与数据挖掘 • 7 年前 • 395 次点击  

在说with语句之前,先看看一段简单的代码吧

lock = threading.Lock()
...
lock.acquire()
elem = heapq.heappop(heap)
lock.release()

很简单直观,多个线程共用一个优先级队列的时候,首先先用互斥锁lock.acquire()把优先级队列锁上,然后取元素,再然后lock.release()释放这个锁。

虽然看似非常符合逻辑的一个过程,但是里面隐藏着一个巨大的bug:当heap里面没有元素的时候,会抛出一个IndexError异常,再然后堆栈回滚,再然后lock.release()根本不会执行,这个锁就永远得不到释放,因此就发生了喜闻乐见的死锁问题。这个也是很多大神们讨厌异常的原因。经典Java风格的解决方案就是

lock = threading.Lock()
...
lock.acquire()
try:
   elem = heapq.heappop(heap)
finally:
   lock.release()

这个虽然可以,但是怎么看怎么dirty,和Python优雅、简单的风格出入很大。其实,自从Python2.5开始引入了with语句,一切就变得非常简单:

lock = threading.Lock()
...
with lock:
   elem = heapq.heappop(heap)

在此无论以何种方式离开with语句的代码块,锁都会被释放。

with语句的设计目的就是为了使得之前需要通过try…finally解决的清理资源问题变得简单、清晰,它的的用法是

with expression [as variable]:
   with-block

其中expression返回一个叫做「context manager」的对象,然后这个对象被赋给variable(如果有的话)。「context manager」对象有两个方法,分别是enter()和exit(),很明显一个在进入with-block时调用,一个离开with-block的时候调用。

这样的对象不需要自己去实现,在Python标准库里面很多API都是已经实现了这两个方法,最常见的一个例子就是读写文件的open语句。

with open('1.txt', encoding = 'utf-8') as fp:
   lines = fp.readlines()

无论是正常离开还是因为异常原因离开with语句块,打开的文件资源总是会释放。

接下去讨论一下with语句配合contextlib库的一些比较实用的方法,比如需要同时打开两个文件,一个读一个写,这个时候就可以这样写:

from contextlib import nested
...
with nested(open('in.txt'), open('out.txt', 'w')) as (fp_in, fp_out):
   ...

这样就可以省掉两个with的语句的嵌套了,另外如果遇到一些还没有支持「context manager」的API呢?比如urllib.request.urlopen(),这个返回的对象因为不是「context manager」,结束的时候还需要自己去调用close方法。

类似这种API,contextlib提供了一个叫做closing方法,它会在离开with语句的时候,自动调用对象的close方法,因此urlopen也可以这样写:

from contextlib import closing
...
with closing(urllib.request.urlopen('http://www.yahoo.com')) as f:
   for line in f:
       sys.stdout.write(line)

学习Python和网络爬虫,关注公众号:datanami

近期文章:

  1. 从0开始玩转MySQL

  2. Python奇技淫巧101

  3. 小白都懂的Python爬虫之网易云音乐下载

  4. Python 实现多线程下载器


今天看啥 - 高品质阅读平台
本文地址:http://www.jintiankansha.me/t/fF4YFv82Fh
Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/25506