Python开发中常用的汇总

1. python主流web框架
1.1 同步框架

​ django, flask, hug

​ 实现原理: wsgi , handler(env, start_response)

​ 部署方式: nginx + web服务器(uwsgi/gunicorn) + web app(django, flask, hug)

1.2 异步框架

​ tornado, sanic, fastapi

​ 实现原理: event_loop(asyncio/gevent) + 协程

​ 部署方式: nginx + web服务器(tornado, sanic, fastapi)

2. 魔术方法的使用
2.1 __new__, __init__
class Person(object):
    __instance = None

    def __new__(cls, *args, **kwargs):
        if Person.__instance is None: 
            obj = object.__new__(cls) 
            Person.__instance = obj
        return Person.__instance   # __new__返回对象实例

    def __init__(self):
        print("创建对象后,进行初始化")   # __init__ 是对象创建后的初始化操作
2.2 __call__ : 可调用对象
class Add(object):
    def __init__(self, a):
        self.a = a
    
    def __call__(b):
        return self.a + b
    
add = Add(1)
add(2)    #   3
2.3 __slots__ : 限制实例的属性
# 提升访问速度(member decriptor), 降低内存使用(__dict__)
class A(object): __slots__ = (x, y)
    
a = A()
a.x, a.y = 1, 2
2.4 __enter__ __exit__ :上下文管理
class LockType(object):
    def acquire():
        pass
    
    def release():
        pass
    
    def __enter__():
        self.acquire()
    
    def __exit__():
        self.release()
        
with LockType() as lock:
    print(1)
2.5 __getitem__, __setitem__
class Member(object):
    def __init__(self):
        self._mydict = {}
        
    def __getitem__(self, key):
        try:
            return self._mydict[key]
        except:
            return None
        
    def __setitem__(self, key, value):
        self._mydict[key] = value
        
m = Member()
m["name"] = "ming"  # 触发__setitem__
name = m["name"]    # 触发__getitem__

#### 3. 装饰器

3.0 装饰器实现原理

函数作为参数: 高级语言可以将函数作为参数使用

闭包:在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用

3.1 不带参数的装饰器
import time

def cal_time(func):
    def wraper(*args, **kwords):
        start = time.time()
        res = func(*args, **kwords)
        print("func cost time:", time.time() - start)
    return wraper

@cal_time
def test():
    print(1111)
3.2 带参数的装饰器
def auth(user_id):
    def decrator(func):
        def wraper(*args, **kwords):
            if user_id:
                return func(*args, kwords)
            else:
                return 403
        return wraper
    return decrator
3.3 类装饰器
class logger(object):
    def __init__(self, func):
        self.func = func

    def __call__(self, *args, **kwargs):
        print("the function {func}() is running..."\
            .format(func=self.func.__name__))
        return self.func(*args, **kwargs)

@logger
def say(something):
    print("say {}!".format(something))

say("hello")
3.4 装饰类的装饰器
def singleton(cls):
    _instance_dict = {}
    def _singleton(*args, **kwords):
        if cls not in _instance_dict:
            _instance_dict[cls] = cls(*args, **kwords):
        return _instance_dict[cls]
    return _singleton

@singleton
class Test(object):
    pass
3.5 装饰器的执行时间,执行顺序
@decorator_b
@decorator_a
def test():
    pass
# 装饰器函数在被装饰函数定义好后立即执行从下往上执行 f=decorator_b(decorator_a(f))
# 函数调用时从上到下执行
3.6 python内置的常见装饰器
from functools import lru_cache

class A(object):
    
    @classmethod              # 类方法,参数为当前类, 类和实例都可以调用
    def a(cls):
        print("aaa")
        
    @staticmethod             # 静态方法,和当前类和实例都没有关系
    def b():
        print("bbbb")
        
    @property                 # 将方法当做属性来使用
    def name(self):
        return "ming"
    
    @lru_cache                # 内存缓存
    def fab(n):
        return n**2
        
a = A()
A.a()
a.a()
A.b()
a.b()
print(a.name)
4. 列表推导式,字典推导式
# 列表推导式
a = [i for i in range(10)]
b = [j for j in a if j > 3]

# 字典推导式
c = {str(index): item for index, item in enumerate(a)}
print("a:", a)    # a: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print("b:", b)    # b: [4, 5, 6, 7, 8, 9]
print("c:", c)    # c: {'0': 0, '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9}
5. 多继承
# 旧式类: 深度优先
# 新式类: 广度优先
class AA(object):
    def toString(s):
        return str(s) * 2
   
class A(AA):
    pass

class B(object):
    def toString(s):
        return str(s) * 3
    
class C(object):
    pass

class D(A, B, C):
    pass

d = D()
d.toString("extend")
# 旧式类调用顺序: D -> A -> AA
# 新式类调用顺序: D -> A -> B
6. 获取属性和设置属性
class A(object):
    
    def toString(self, s):
        return str(s)
        
class B(object):
    pass
        
def trans(obj, s):
    if hasattr(obj, "toString"):
        res = getattr(obj, "toString")(s)             # 类似的用法:  eval("{'a': 1, 'b': 2}")  返回传入字符串的表达式的结果
    else:                                             # eval的危害: eval("os.system('rm -rf *')")
        setattr(obj, "toString", lambda s: str(s)*2)
        toString = getattr(obj, "toString")
        res = toString(s)
        
a = A()
b = B()
trans(a, "aa")
trans(b, "bb")
7. 元编程
7.1 元类

定义: 创建类的类

使用__class__查看对象是由哪个类创建的

class A(object):
    pass
print("元类:", A.__class__)
# 元类:type

type: 创建类的类

type创建类的语法

# type(类名, 由⽗类名称组成的元组(针对继承的情况,可以为空), 包含属性的字典)
def upper(self):
    return self.name.upper()

B = type("B",(object,),{
    "name": "ming",
    "name_upper": upper
})
b = B()
b.name_upper()
7.2 创建一个元类
# metaclass 
class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class Application(metaclass=Singleton):  # python3 用法
    pass

#class Application(object):  # python2 用法
#    __metaclass__=Singleton

# 调用顺序: singleton.__new__, singleton.__init__ 创建Application类, 创建Application实例时调用 singleton.__call__
8. 多线程编程
8.1 线程的使用场景

使用场景: io密集型任务

原 因: 由于GIL锁的存在,所以同一时间同一个进程内只有一个线程在cpu上执行,所以严格说python多线程只能实现并发,而不是并行

8.2 线程的使用方法
# 线程的基本使用
import time
from threading import Thread, Lock

def test(n):
    time.sleep(n)
    
td = Thread(target=test, args=(5,))
td.start()
td.join()          # 主线程会阻塞,直到td线程执行结束

# 线程常见用法
class Heartbeat(Thread):
    def __init__(self, connection):
        super().__init__()
        self.lock = Lock()
        self.connection = connection
        self.heartbeat_interval = int(getattr(connection, '_impl').params.heartbeat / 2)
        self.setDaemon(True)  # 主进程结束了但该守护线程没有运行完,守护进程就会被强制结束

    def run(self):
        while True:
            time.sleep(self.heartbeat_interval)
            self.lock.acquire()
            try:
                self.connection.process_data_events()
            # 心跳检测连接关闭不记录错误日志,cmsk等客户环境流程是正常的出现很多错误日志
            except ConnectionClosed:
                pass
            except BaseException as ex:
                logging.exception(ex)
            finally:
                self.lock.release()
                
# 线程池用法
from concurrent.futures import ThreadPoolExecutor
import time

def spider(page):
    time.sleep(page)
    print(f"crawl task{page} finished")
    return page

with ThreadPoolExecutor(max_workers=5) as t:  # 创建一个最大容纳数量为5的线程池
    obj_list = []
    for page in range(1, 5):
        obj = t.submit(spider, page)     # 通过submit提交执行的函数到线程池中
        obj_list.append(obj)

    for future in as_completed(obj_list):  # as_completed 当子线程中的任务执行完后,直接用 result() 获取返回结果
        data = future.result()
        print(f"main: {data}")
9. 多进程编程
9.1 调用外部程序
# 在cmd中调起外部程序, 阻塞的方式
os.system(command="python test.py")

# 在cmd中调起外部程序, 非阻塞的方式
import subprocess
process = subprocess.Popen(command="python test.py", stderr=subprocess.PIPE)
# 终止进程
# process.kill()	

# communicate: 当前线程阻塞,直到子进程执行结束
stdout, stderr = process.communicate(timeout=172800)
9.2 开启子进程执行函数
# 使用场景
# cpu密集型程序

# 和threading使用方式相同
import multiprocessing
import time

def worker(n):
    time.sleep(n)

for i in range(5):
   process = multiprocessing.Process(target=worker, args=(5,))
   process.start()
   record.append(process)
    
for process in record:
   process.join()
9.3 进程池
from multiprocessing.pool import ThreadPool

def worker(n):
    time.sleep(n)

# 设置最大并行数
pool = ThreadPool(processes=3)
# apply_async(func,args) 从进程池中取出一个进程执行func,args为func的参数。它将返回一个AsyncResult的对象,你可以对该对象调用get()方法以获得结果。
result = pool.apply_async(worker, args=(5,))

pool.close()       # 进程池不再创建新的进程

pool.join()        # wait进程池中的全部进程。必须对Pool先调用close()方法才能join。
9.4 进程间通讯
# pipe  只支持两个进程间传递
import multiprocessing as mul

def proc1(pipe):
    pipe.send('hello')
    print('proc1 rec:', pipe.recv())

def proc2(pipe):
    print('proc2 rec:', pipe.recv())
    pipe.send('hello, too')

# Pipe对象返回一个含有两个元素的表,每个元素代表Pipe的一端。我们对Pipe的某一端调用send()方法来传送对象,在另一端使用recv()来接收。
pipe = mul.Pipe()
if __name__ == '__main__':
    p1 = mul.Process(target=proc1, args=(pipe[0],))
    p2 = mul.Process(target=proc2, args=(pipe[1],))
    p1.start()
    p2.start()
    p1.join()
    p2.join()
    
    
    
# Queue 支持多个进程间传递
import os
import multiprocessing
import time

def inputQ(queue):
    info = str(os.getpid()) + '(put):' + str(time.time())
    queue.put(info)

def outputQ(queue):
    info = queue.get()
    print (str(os.getpid()) + ' get: ' + info)

record1 = [] 
record2 = [] 

queue = multiprocessing.Queue(3)  # 设置队列大小

if __name__ == '__main__':
    for i in range(5):
        process = multiprocessing.Process(target=inputQ,args=(queue,))
        process.start()
        record1.append(process)
    
    for i in range(5):
        process = multiprocessing.Process(target=outputQ,args=(queue,))
        process.start()
        record2.append(process)
    
    for p in record1:
        p.join()
    
    queue.close()  # 不再接受新的数据
    
    for p in record2:
        p.join()
10. 生成器和协程
10.1 创建生成器
b = (i for i in range(10))   
print(b)                      # <class 'generator'>

def test(a):
    yield a
print(test(3))                # <generator object test at 0x00000283083CD8E0>
10.2 生成器的迭代
# 同其他可迭代对象一样迭代
b = (i for i in range(10)) 
for i in b:
    print(i)
    
# next()方法
def test():
    for i in range(3):
        yield i                # yield返回一个值
b = test()
print(next(b))  # 0
print(next(b))  # 1
print(next(b))  # 2
# print(next(b))  StopIteration error
10.3 生成器的控制----协程
# 生成器的send方法
def consumer():
    r = ''
    while True:
        n = yield r   # send(x)  由n接收x的值
        if not n:
            return
        print('[CONSUMER] Consuming %s...' % n)
        r = '200 OK'

def produce(c):
    c.send(None)     # 启动生成器
    # next(c)        # 也可以用next启动生成器
    n = 0
    while n < 2:
        n = n + 1
        print('[PRODUCER] Producing %s...' % n)
        r = c.send(n)
        print('[PRODUCER] Consumer return: %s' % r)
    c.close()        # 关闭携程

c = consumer()
produce(c)

# [PRODUCER] Producing 1...
# n: 1
# [CONSUMER] Consuming 1...
# [PRODUCER] Consumer return: 200 OK
# [PRODUCER] Producing 2...
# n: 2
# [CONSUMER] Consuming 2...
# [PRODUCER] Consumer return: 200 OK
11. 异步编程
11.1 asyncio
11.1.0 asyncio用法
import asyncio

# @asyncio.coroutine 协程预激装饰器
async def hello():               # python3.5以后的新语法 async代替协程预激装饰器, await代替yield from, 以同步的方式写异步程序
    print("Hello world!")
    r = await asyncio.sleep(1)   # 异步调用asyncio.sleep(1):
    print("Hello again!")

# 获取EventLoop:
loop = asyncio.get_event_loop()
# 执行coroutine
loop.run_until_complete(hello())
loop.close()
11.1.1 用协程实现单进程并发
# 和线程实现并发的区别

import asyncio
  
import time
  
async def do_some_work(x):
    print('Waiting: ', x)
  
    await asyncio.sleep(x)
    print('Done after {}s'.format(x))
  
start = time.time()
  
coroutine1 = do_some_work(3)
coroutine2 = do_some_work(5)
  
tasks = [
    asyncio.ensure_future(coroutine1),    # ensure_future 可以将 coroutine 封装成 Task
    asyncio.ensure_future(coroutine2),
]
  
loop = asyncio.get_event_loop()
# asyncio.wait方法则返回一个 coroutine。
# run_until_complete 既可以接收 Future 对象,也可以是 coroutine 对象,如果是coroutine,则先把他转化为future
loop.run_until_complete(asyncio.wait(tasks))   # loop.run_until_complete(asyncio.gather(coroutine1, coroutine1))
  
print('TIME: ', time.time() - start)
11.1.2 event_loop原理

io多路复用:

​ windows: select

​ linux : epoll

11.1.3 asyncio异步调度原理
# Future 表示未来要完成的事情.
class Future:
    def __init__(self):
        self.result = None
        self._callbacks = []

    def add_done_callback(self, fn):
        self._callbacks.append(fn)

    def set_result(self, result):
        self.result = result
        for fn in self._callbacks:   # set_result会调用call_back
            fn(self)
            
# Task是用来驱动future的
class Task:
    def __init__(self, coro):
        self.coro = coro
        f = Future()
        f.set_result(None)  # 激活协程
        self.step(f)

    def step(self, future):
        try:
            next_future = self.coro.send(future.result)    # 通过send方法来控制协程
        except StopIteration:
            return

        next_future.add_done_callback(self.step)          # callback中就是step方法
11.2 gevent
11.2.0 gevent实现并发(基于IO切换的协程)
# 由于切换是在IO操作时自动完成,所以gevent需要修改Python自带的一些标准库,这一过程在启动时通过monkey patch完成:
from gevent import monkey; monkey.patch_all()
import gevent
import urllib2

def f(url):
    print('GET: %s' % url)
    resp = urllib2.urlopen(url)
    data = resp.read()
    print('%d bytes received from %s.' % (len(data), url))

gevent.joinall([                                       # 将协程任务添加到事件循环,接收一个任务列表
        gevent.spawn(f, 'https://www.python.org/'),    # 创建一个普通的Greenlet对象并切换
        gevent.spawn(f, 'https://www.yahoo.com/'),
        gevent.spawn(f, 'https://github.com/'),
])
11.2.1 原理

event_loop: 基于libev的事件循环

协程 : 当处理一个socket链接时,就创建一个协程greenlet(c拓展库实现)去处理,遇到io操作自动切换

11. 3 asyncio和gevent的区别

gevent:

  • python2 需要通过yield + 回调 的方式去实现异步编程,gevent可以使web app以同步的开发方式实现异步编程
  • gevent 会在遇到io操作时自动切换,适合无脑开发

asyncio:

  • asyncio是在python3.4的时候被加入标准库
  • python3.5时支持async await 语法, 让python可以以同步的方式开发异步程序
  • asyncio是由用户自己控制阻塞的时机, 所以需要使用异步的io库才能实现真正的异步
  • 目前异步io库还不全,成熟的有:aiohttp, aioredis, aiopika等, 没有成熟且好用的orm(mysql)框架
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值