前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >python with魔法语句

python with魔法语句

作者头像
py3study
发布2020-01-08 17:50:11
4680
发布2020-01-08 17:50:11
举报
文章被收录于专栏:python3

通常之前我们在打开文件的时候都是:

代码语言:javascript
复制
file = open("a.txt")
try:  
  data = file.read()
finally:    
   file.close()

*每一个打开文件之后要关闭文件描述符,但是使用with语句则不用:

代码语言:javascript
复制
whih open("a.txt") as f:
   print f.readline()

这个是with默认封装的好的一个魔法盒子,封装了__enter__和__exit__两个函数:

为了我们自己的类也可以使用with, 只要给这个类增加两个函数__enter__, __exit__即可:

>>> class A: ...      def __enter__(self): ...         print "in enter" ...      def __exit__(self, a, b, c): ...         print "in exit" >>> with A() as a:           ...     print "in with"

... in enter in with in exit

*可以看到当我们使用with的适合最先调用的是__enter__函数,然后进行下面的操作,结束之后才到__exit__函数:

写一个类似打开文件的操作:

代码语言:javascript
复制
#!/usr/bin/env python
class demo:
    def __init__(self, path, mode):
        self.path = path
        self.mode = mode
    def __enter__(self):
        return self
    def write(self, text):
        print self.path,self.mode
        print(text)
    def __exit__(self, a, b ,c):
        return True
with demo("attr.py","w") as f:
    f.write("hello world")

执行效果:
[root@monitor python]# python test_with.py 
attr.py w
hello world

*这里把打开文件读取,转换成打印传入的参数和执行with里面write函数的操作。

__exit__方法里面的,a,b,c分别表示:异常类型如value.Error、异常描述、Traceback;当使用return True 时候表示会捕获异常,return False时候表示会抛出异常。

提示异常操作:

代码语言:javascript
复制
#!/usr/bin/env python
class demo:
    def __init__(self, path, mode):
        self.path = path
        self.mode = mode
    def __enter__(self):
        return self
    def write(self, text):
        print self.path,self.mode
        print(text)
    def __exit__(self, a, b ,c):
        print a
        print b
        print c
        return True
with demo("a.py","w") as f:
    f.write("hello world")
    int("error")

执行效果:

代码语言:javascript
复制
[root@monitor python]# python test_with.py 
a.py w
hello world
<type 'exceptions.ValueError'>
invalid literal for int() with base 10: 'error'
<traceback object at 0xb3e3f8>

这样with可以帮助我们完成很多重复操作,比如初始化,连接数据库,关闭数据库;socket等多个重复操作。

举例用with语法往graphite的socker监听端口打数据。

代码语言:javascript
复制
#!/usr/bin/python
# coding:utf-8
import errno
import time
import socket
class CarbonClient(object):
    def __init__(self, host, port):
        self._host = host
        self._port = port
        self._carbon = None
        self._connected = None
    def connect(self):
        """
            建立socket连接
        """
        if not self._connected:
            self._connect()
    def connected(self):
        return self._connected
    def _connect(self):
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        while 1:
            try:
                sock.connect((self._host, self._port))
            except socket.error as e:
                if e.errno == errno.EINTR:
                    continue
                else:
                    raise e
            break
        self._carbon = sock
        self._connected = True
    def close(self):
        if self._connected:
            self._carbon.close()
            self._connected = False
    def send(self, metrics):
        chunk_start, chunk_end = 0,20
        while 1:
            payload = []
            metrics_chunk = metrics[chunk_start: chunk_end]
            if not metrics_chunk:
                break
            for metric in metrics_chunk:
                if len(metric) == 2:
                    payload.append("{} {} {}\n".format(metric[0], metric[1], int(time.time())))
                elif len(metric) == 3:
                    payload.append("{} {} {}\n".format(*metric))
                else:
                    raise ValueError("Error format data")
            self._carbon.sendall("".join(payload))
            chunk_start, chunk_end = chunk_end, chunk_end + 20
    def __enter__(self):
        self.connect()
        return self
    def __exit__(self, exec_type, exec_value, exc_tb):
        self.close()
        return exec_value is None
class RebootCarbonClient(CarbonClient):
    REBOOT_CARBON_ADDR = ("192.168.1.54", 2003)
    def __init__(self):
        super(RebootCarbonClient, self).__init__(*self.REBOOT_CARBON_ADDR)
"""
    1条:
        (key, value, time)
        (key, value)
    多条
        [(key, value), (key, value)]
graphite api
"""
if __name__ == "__main__":
    with RebootCarbonClient() as client:
        client.send([("hostname.sys.mem.usage", '1096'), ("hostname.sys.mem.usage", '2048')])
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019/09/03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档