zoukankan      html  css  js  c++  java
  • Python With语句

    不得不说派森大法好!

    最近读代码发现了with这个好东西,通常可用于替换try,或者用在锁区域,出了这段代码锁自然释放这点跟java的synchronized关键词有点像,看个代码:

    _pool_create_sem = threading.Lock()
    def get_connection_pool(conf, connection_cls):
        with _pool_create_sem:
            # Make sure only one thread tries to create the connection pool.
            if not connection_cls.pool:
                connection_cls.pool = ConnectionPool(conf, connection_cls)
        return connection_cls.pool
    

    在进入with后面的语句块内时,必定获得了锁,到达return语句时必然已经释放了锁(即使有异常抛出也会释放),再也不用担心忘记解锁了。

    派森大法中把像_pool_create_sem这样的对象称作 With Statement Context Manager,如果想在with中使用自己定义类的实例对象,就要在类中实现下面两个方法:

    object.__enter__(self)

    Enter the runtime context related to this object. The with statement will bind this method’s return value to the target(s) specified in the as clause of the statement, if any.

    object.__exit__(selfexc_typeexc_valuetraceback)

    Exit the runtime context related to this object. The parameters describe the exception that caused the context to be exited. If the context was exited without an exception, all three arguments will be None.

    If an exception is supplied, and the method wishes to suppress the exception (i.e., prevent it from being propagated), it should return a true value. Otherwise, the exception will be processed normally upon exit from this method.

    Note that __exit__() methods should not reraise the passed-in exception; this is the caller’s responsibility.

    __enter__在进入with后面的代码段之前执行,可以进行一些准备工作,比如把锁给锁上。__exit__在with后面的代码段退出时执行,可以进行一些资源的清理工作。尝试一发:

    >>> class FakeLock(object):
    ...     def __enter__(self):
    ...             print 'locked'
    ...     def __exit__(self, exc_type, exc_value, traceback):
    ...             print 'unlocked'
    ...
    >>> with FakeLock():
    ...     print "I'm safe"
    ...
    locked
    I'm safe
    unlocked
    

    可以看到__exit__方法还可以有许多参数都是关于with语句块内发生异常时的情况,一样我们可以把异常处理放在__exit__函数中,不必在写冗长的try语句了。

    另外with语句可以可以有一个as关键词用于声明一个with使用的对象的别名,这样我们就能在with语句块内使用它了,经常出现在基于连接,读写文件的操作上,贴代码:

    >>> with open('e:/static.txt') as f:
    ...     f.readline()
    ...
    'auto eth0
    '
    

    这样就不用手工去close file了,不过这里它似乎没有对异常进行处理会直接抛出。下面来自己写一个,这时__enter__方法需要有一个返回值,这个返回值就会赋给with as后面的变量

    >>> class FakeConnection(object):
    ...     def __enter__(self):
    ...             print 'connection established!'
    ...             return self
    ...     def __exit__(self, ex_type, ex_value, traceback):
    ...             if ex_type is not None:
    ...                     print 'execption detected:', ex_type, ex_value
    ...             print 'connection disconnected!'
    ...             return True
    ...     def send(self):
    ...             print 'msg send'
    ...
    

    先定义一个假的连接对象,在__enter__中建立连接,然后返回自身。在__exit__中会记录抓到的异常(如果后面三个参数不为None),并断开连接,返回True表示异常以及被处理,不会再向上层调用者传递。运行一发:

    >>> with FakeConnection() as conn:
    ...     conn.send()
    ...
    ...
    connection established!
    msg send
    connection disconnected!
    >>> with FakeConnection() as conn:
    ...     conn.send()
    ...     conn.methodNotExist()
    ...
    connection established!
    msg send
    execption detected: <type 'exceptions.AttributeError'> 'FakeConnection' object has no attribute 'methodNotExist'
    connection disconnected!
    

      

  • 相关阅读:
    Leetcode-Spiral Matrix
    Leetcode-Permuation Sequence
    浪潮服务器硬盘坏道数据恢复
    通过拼数据库碎片的方式恢复虚拟机磁盘文件丢失问题
    aix 6.1系统怎么安装?这里有详细图文教程
    技术文档分享_linux中生成考核用的GPT分区表结构修复
    python解释NTFS runlist的代码(文章转自北亚数据恢复张宇工程师)
    Unix下zfs文件系统重组RAID-5后可以这样恢复
    EXT3文件系统误删除导致文件系统中的邮件丢失恢复方法
    Hyper-V虚拟机故障导致数据文件丢失的数据恢复全过程
  • 原文地址:https://www.cnblogs.com/lailailai/p/3893817.html
Copyright © 2011-2022 走看看