python多线程,并发和锁

多任务 同一个时间有多个任务在执行 python程序默认是单任务 线程 线程概念 线程,可简单理解为是程序执行的一条分支,也是程序执行流的最小单元。 线程是被系统独立调度和分底的基本单位,线程自己不拥有系统资源,只拥有一点儿在运行中必不可少的资源,但它可与同属一个进程为其它线程共享进程所拥有的全部资源。 主线程 当一个程序后动时,就有一个进程被操作系统(OS)创建,与此同时一个线程也立刻运行,该线程通常叫做程序的主线程,简而言之;程序后动就会创建一个主线程。 Copy主线程的重要性有两方面: 1)是产生其他子线程的线程; 2)通常它必须最后完成执行比如执行各种关闭动作· ...

7 min · 3206 words · Luenci

python的值传递和引用传递

函数的传参 函数参数传递机制问题在本质上是调用函数(过程)和被调用函数(过程)在调用发生时进行通信的方法问题。基本的参数传递机制有两种:值传递和引用传递。 值传递(pass-by-value)过程中,被调函数的形式参数作为被调函数的局部变量处理,即在堆栈中开辟了内存空间以存放由主调函数放进来的实参的值,从而成为了实参的一个副本。值传递的特点是被调函数对形式参数的任何操作都是作为局部变量进行,不会影响主调函数的实参变量的值。 引用传递(pass-by-reference)过程中,被调函数的形式参数虽然也作为局部变量在堆栈中开辟了内存空间,但是这时存放的是由主调函数放进来的实参变量的地址。被调函数对形参的任何操作都被处理成间接寻址,即通过堆栈中存放的地址访问主调函数中的实参变量。正因为如此,被调函数对形参做的任何操作都影响了主调函数中的实参变量。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 In [1]: from ctypes import * In [2]: import os.path In [3]: import sys \# 传入不可变类型 In [4]: def test(x): ...: print("test before") ...: print(id(c)) ...: c+=2 ...: print("test add") ...: print(id(c)) ...: return c In [5]: a = 2 In [6]: id(2) Out[6]: 11496672 In [7]: n = test(a) test before 11496672 test add 11496736 \# 传入可变类型 In [17]: def test2(x): ...: print("test before") ...: print(id(x)) ...: x[0] = 45 ...: print("test after") ...: print(id(x)) ...: return x ...: In [18]: e = [0,1,2,3] In [19]: id(e) Out[19]: 140323019352896 In [20]: g = test2(e) test before 140323019352896 test after 140323019352896 结论:python不允许程序员选择采用传值还是传引用。Python参数传递采用的肯定是“传对象引用”的方式。这种方式相当于传值和传引用的一种综合。 如果函数收到的是一个可变对象(比如字典或者列表)的引用,就能修改对象的原始值--相当于通过“传引用”来传递对象。 如果函数收到的是一个不可变对象(比如数字、字符或者元组)的引用,就不能直接修改原始对象--相当于通过“传值’来传递对象。 ...

2 min · 967 words · Luenci

python的协程

可迭代对象 可遍历对象就是可迭代对象 列表、元组、字典、字符串都是可迭代对象 100和自定义myclass 默认都是不可以迷代的 myclass 对象所属的类MyClass如果包含了__iter__()方法,此时 myclass就是一个可送代对象 可送代对象的本质:对象所属的类中包含了__iter__()方法 检测一个对象是否可以送代,用isinstance()函数检测。 迭代器 我们发现选代器最核心的功能就是可以通过next0函数的调用来返回下一个数据值。如果每次返回的数据值不是在一个已有的数据集合中读取的,而是通过程序按照一定的规律计算生成的,那么也就意味着可以不用再依赖一个已有的数据集合,也就是说不用再将所有要迭代的数据都一次性缓存下来供后续依次读取,这样可以节省大量的存储(内存)空间。 举个例子,比如,数学中有个著名的斐波拉契数列(Fibonacci),数列中第一个数为0,第二个数为1,其后的每一个数都可由前两个数相加得到: 特点 记录遍历的位置 ...

8 min · 3838 words · Luenci

Python的模块和类

import导入模块路径问题 存在的问题:当我们把模块文件放到工程文件夹的外部的文件,发现无法正常引入模块 原因:外部的文件夹的路径,没有放到环境变量中。 查看环境变量 1.导入sys模块 2.sys.path 查看环境变量返回值是列表 把自己写的模块的路径加入到环境变量中 ...

12 min · 5938 words · Luenci

python的进程,线程和协程对比

概念 进程 ​ 进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位。每个进程都有自己的独立内存空间,不同进程通过进程间通信来通信。由于进程比较重量,占据独的内存,所以上下文进程间的切换开销(栈、寄存器、虚拟内存、文件句柄等)比较大,但相对比较稳定安全。 线程 ​ 线程是进程的一个实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位.线程自己基本上不拥有系统资源,只拥有一点在运行中必不可少的资源(如程序计数器,一组寄存器和栈),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。线程间通信主要通过共享内存,上下文切换很快,资源开销较少,但相比进程不够稳定容易丢失数据。 协程 ​ 协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。 三者关系 ...

2 min · 733 words · Luenci

python的进程概念

进程 进程概念 进程(Process)是资源分配的最小单位,是线程的容器。 程序是固定不变的,而进程会根据运行需要,让操作系统动态分配各种资源的CPU的时间片轮转,在不同的时间段切换执行不同的进程,但是切换进程是比较耗时的;就引来了轻量级进程,也就是所谓的线程,一个进程中包括多个线程(代码流,其实也就是进程中同时跑的多个方法体) 程序:例xxx.py这是程序,是一个静态的 进程:一个程序运行起来后,代码+用到的资源称之为进程,它是操作系统分配资源的基本单元。 进程状态 工作中,任务数往往大于cpu的核数,即一定有一些任务正在执行,而另外一些任务在等待cpu进行执行,因此导致了有了不同的状态 进程状态 就绪态:运行的条件都已经满足,正在等在cpu执行 执行态:cpu正在执行其功能 等待态:等待某些条件满足,例如一个程序sleep了,此时就处于等待态 进程的创建 - multiprocessing multiprocessing模块就是跨平台版本的多进程模块,提供了一个Process类来代表一个进程对象,这个对象可以理解为是一个独立的进程,可以执行另外的事情。 ·创建子进程跟创建线程十分类似,只需要传入一个执行函数和函数的参数,创建一个Process实例,用start0方法后动 Process语法结构如下: Process([group [,target[,name,[args[,kwargs]]]) target:如果传递了函数的引用,这个子进程就执行这里(函数)的代码 args:给target指定的函数传递的参数,以元组的方式传递 kwargs:给target指定的函数传递命名参数 name:给进程设定一个名字,可以不设定 group:指定进程组,大多数情况下用不到 Process创建的实例对象的常用方法: start():后动子进程实例(创建子进程) is_alive:判断进程子进程是否还在活着 join([timeout]):是否等待子进程执行结束,或等待多少秒o terminate:不管任务是否完成,立即终止子进程 Process创建的实例对象的常用属性: name:当前进程的别名,默认为Process-N,N为从1开始递增的整数 pid:当前进程的pid(进程号) linux系统可使用kill命令结束进程 ...

9 min · 4160 words · Luenci

python的闭包和装饰器

闭包 引入 函数名是一个特殊的变量,保存了函教的地址和 自定义一个变量可以获取函数地址 自定义变量调用函数 “函数名()” 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 def work(): print("我是一个测试函数") ret = work print(ret) print("地址:%X" % id(ret)) print("地址:%X" % id(work)) ret() work() out: <function work at 0x00000161E3091E18> 地址:161E3091E18 地址:161E3091E18 我是一个测试函数 我是一个测试函数 当我们定义函数test1后,函数名test1保存的是函数在内存的首地址函数名就是一个特殊的变量,函数名()调用函数,执行函数体test1()和ret()都会调用函数,并执行函数体 和变量名一样的,函数名数名只是函数代码空间的引用,当函数名赋值给一个对象的时候就是引用传递。 闭包概念 在一个外函数中定义了一个内函数,内函数里运用了外函数的临时变量,并且外函数的返回值是内函数的引用。这样就构成了一个闭包 ...

5 min · 2165 words · Luenci

Python类中的 私有变量 和 私有方法

Python中的类 原文转自:https://blog.csdn.net/sxingming/article/details/52875125 默认情况下,Python中的成员函数和成员变量都是公开的(public),在python中没有类似public,private等关键词来修饰成员函数和成员变量。 在python中定义私有变量只需要在变量名或函数名前加上 __两个下划线,那么这个函数或变量就是私有的了。 在内部,python使用一种 name mangling 技术,将 __membername替换成 _classname__membername,也就是说,类的内部定义中,所有以双下划线开始的名字都被"翻译"成前面加上单下划线和类名的形式。 例如:为了保证不能在class之外访问私有变量,Python会在类的内部自动的把我们定义的__spam私有变量的名字替换成为 _classname__spam(注意,classname前面是一个下划线,spam前是两个下划线),因此,用户在外部访问__spam的时候就会提示找不到相应的变量。 python中的私有变量和私有方法仍然是可以访问的 访问方法如下: 私有变量:实例._类名__变量名 私有方法:实例._类名__方法名() 其实,Python并没有真正的私有化支持,但可用下划线得到伪私有。 尽量避免定义以下划线开头的变量! (1)_xxx “单下划线 " 开始的成员变量叫做保护变量,意思是只有类实例和子类实例能访问到这些变量, 需通过类提供的接口进行访问;不能用’from module import *‘导入 (2)__xxx 类中的私有变量/方法名 (Python的函数也是对象,所以成员方法称为成员变量也行得通。), " 双下划线 " 开始的是私有成员,意思是只有类对象自己能访问,连子类对象也不能访问到这个数据。 (3)__xxx__ 系统定义名字,前后均有一个“双下划线” 代表python里特殊方法专用的标识,如 __init__()代表类的构造函数。 ...

4 min · 1561 words · Luenci

Python类补充

item系列 __getitem__ 以字典形式访问属性的时候触发 __setitem__ 以字典形式设置属性的时候触发 __delitem__ 以字典形式删除属性的时候触发 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 class Demo(object): def __getitem__(self, item): print("触发__getitem__") def __setitem__(self, key, value): print("触发__setitem__") self.__dict__[key] = value def __delitem__(self, key): print("触发__delitem__") self.__dict__.pop(key) f = Demo() # 以字典的方式来操作属性 print(f.__dict__) f['name'] = 'luenci' print(f.__dict__) print(f['name']) del f['name'] print(f.__dict__) out: {} 触发__setitem__ {'name': 'luenci'} 触发__getitem__ None 触发__delitem__ {} __str__和__repr__控制输出 __str__会在print()打印时候调用,如果类中没重写则会调用默认的打印值,如果自定义了则会调用自定义的__str__方法 __repr__这个实在控制台的时候输出,若一个类中没定义__str__但是定义了__repr__方法,则会调用__repr__的返回值。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class bar(object): def __init__(self, name, age): self.name = name self.age = age # def __str__(self): # return '__str__自定义返回值' def __repr__(self): return '__repr__自定义返回值' f = bar('luenci', 18) # print() 函数触发__str__()函数 print(f) out: __repr__自定义返回值 __slots__属性 1.__slots__是什么? ...

5 min · 2176 words · Luenci

python解释器介绍

CPython 当我们从Python官方网站下载并安装好Python 3.x后,我们就直接获得了一个官方版本的解释器:CPython。这个解释器是用C语言开发的,所以叫CPython。在命令行下运行python就是启动CPython解释器。 ...

2 min · 652 words · Luenci

python解释器的GIL锁

GlL锁定义 Gll锁:Global Interpreter Lock,又称:全局解释器锁 任何Python线程执行前,必须先获得GlL锁,然后,每执行100条字节码,解释器就自动释放GL锁,让别的线程有机会执行。这个GlL全局锁实际上把所有线程的执行代码都给上了锁,所以,多线程在Python中只能交替执行,即使100个线程跑在100核CPU上,也只能用到1个核。 ...

5 min · 2127 words · Luenci

Python面向对象

类的定义 把一类事物的相同的特征和动作整合到一起就是类,类是一个抽象的概念 对象的定义 基于类而创建一个具体的事物,类的实例化 接口继承 继承的第二种含义非常重要。它又叫“接口继承”。 接口继承实质上是要求“做出一个良好的抽象,这个抽象规定了一个兼容接口,使得外部调用者无需关心具体细节,可一视同仁的处理实现了特定接口的所有对象”——这在程序设计上,叫做归一化。 归一化使得高层的外部使用者可以不加区分的处理所有接口兼容的对象集合——就好象linux的泛文件概念一样,所有东西都可以当文件处理,不必关心它是内存、磁盘、网络还是屏幕(当然,对底层设计者,当然也可以区分出“字符设备”和“块设备”,然后做出针对性的设计:细致到什么程度,视需求而定)。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 # 导入抽象基类模块 import abc # 定义接口(基类) class File(metaclass=abc.ABCMeta): @abc.abstractmethod def read(self): pass @abc.abstractmethod def write(self): pass class disk(File): def read(self): print("disk read") def write(self): print("disk wirte") ds = disk() ds.read() 子类中调用父类的方法 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 class Grandfather(object): def __init__(self, name, age): self.age = age self.name = name def grandfather(self): print("grandfather method") class Father(Grandfather): def __init__(self, name, age): super().__init__(name,age) def father_method(self): print("father method") class Son(Father): def __init__(self, name, age,sex): # 调用父类的构造方法 super().__init__(name,age) self.sex = sex # 子类中调用父类方法 def son_method(self): Father.father_method(self) def son_method1(self): super().grandfather() son1 = Son('xiaoming',18, 'male') son1.son_method1() 组合 1、组合指的是,在一个类中以另外一个类的对象作为数据属性,称为类的组合。 2、作用是可以将两个本来不相关的类联系起来。一般是两个类之间有显著的不同,很多时候还要附属关系(有相同的属性也有不同的属性)。比如人和头,手机和电池等等。 3、无纵向关系时用组合,有纵向关系时用继承。 4、组合就是一个类中使用到另一个类,从而把几个类拼到一起。组合的功能也是为了减少重复代码 多态 由不同的类实例化得到的对象,调用同一个方法,执行的逻辑不同 多态的概念指出了对象如何通过他们共同的属性和动作来操作及访问,而不需考虑他们具体类。 多态表明了动态(又名,运行时)绑定的存在,允计重载及运行时类型确定和验证。 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 class People(object): def __init__(self, name, age): self.name = name self.age = age def generation(self): if self.age < 18: print("[%s]属于未成年人" % self.name) elif 18 < self.age < 30: print("[%s]属于青年人" % self.name) else: print("[%s]属于中老年人" % self.name) class minor(People): pass class young(People): pass class old(People): pass def func(obj): obj.generation() w1 = young('luenci',20) w2 = minor('xiaoming', 16) w3 = old('jack', 50) func(w1) func(w3) func(w3) out: [luenci]属于青年人 [jack]属于中老年人 [jack]属于中老年人 反射 getattr(object, name) 得到属性的值 hasattr(object, name) 说明:判断对象object是否包含名为name的特性(hasattr是通过调用getattr(ojbect, name)是否抛出异常来实现的 setattr(object, name, value) 这是相对应的getattr()。参数是一个对象,一个字符串和一个任意值。字符串可能会列出一个现有的属性或一个新的属性。这个函数将值赋给属性的。该对象允许它提供。例如,setattr(x,“foobar”,123)相当于x.foobar= 123 delattr(object, name) 与setattr()相关的一组函数。参数是由一个对象(记住python中一切皆是对象)和一个字符串组成的。string参数必须是对象属性名之一。该函数删除该obj的一个由string指定的属性。delattr(x, 'foobar')=del x.foobar 注:getattr,hasattr,setattr,delattr对模块的修改都在内存中进行,并不会影响文件中真实内容。 ...

6 min · 2837 words · Luenci

socket网络编程实战-斗鱼弹幕获取

asyncore模块 介绍 这个模块为异步socket的服务器客户端通信提供简单的接口。 该模块提供了异步socket服务客户端和服务器的基础架构。 相比python原生的socket api,asyncore具备有很大的优势,asyncore对原生的socket进行封装,提供非常简洁优秀的接口,利用asyncore覆写相关需要处理的接口方法,就可以完成一个socket的网络编程,从而需要处理复杂的socket网络状况以及多线程处理等等。 实现流程 客户端 Socket 开发基本使用 1.定义类继承自asyncore.dispatcher 2.实现类中的回调代码 实现构造函数 调用父类方法 创建 Socket对象 连接服务器 实现handle_connect回调函数 当socket连接服务器成功时回调该函数 实现writable回调函数 描述是否有数据需要被发送到服务器。返回值为True表示可写,False表示不可写,如果不实现默认返回为True,当返回True时,回调函数handle_write将被触发 实现handle_write 回调函数 当有数据需要发送时(writable回调函数返回True时),该函数被触发,通常情况下在该函数中编写send方法发送数据 实现readable回调函数 描述是否有数据从服务端读取。返回True 表示有数据需要读取,False表示没有数据需要被读取,当不实现默认返回为True,当返回True 时,回调函数handle_read将被触发 实现handle_read 回调函数 当有数据需要读取时触发(readable回调函数返回True 时),该函数被触发,通常情况下在该函数中编写recv方法接收数据 实现handle_error回调函数 当程序运行过程发生异常时回调 实现handle_close回调函数 当连接被关闭时触发 3.创建对象并且执行asyncore.loop进入运行循环 timeout表示一次循环所需要的时长 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 import asyncore import sys # 定义类继承自 asyncore.dispather class scoket_client(asyncore.dispatcher): # 实现类中的回调代码 def __init__(self, host, port): # 调用父类的方法 asyncore.dispatcher.__init__(self) # 创建 Scoket 服务器 self.create_socket() # 连接地址 address = (host, port) self.connect(address) pass # 实现handle_connect回调函数 def handle_connect(self): print("连接成功") # 实现writable函数 def writable(self): return False # 实现handle_write回调函数 def handle_write(self): # 内部实现对服务器发送数据代码 # 调用 send 方法发送数据,参数是字节数据 self.send("hello world".encode('utf-8')) # self.send("hello world") # 实现readable回调函数 def readable(self): return True # 实现handle_read回调函数 def handle_read(self): # 主动接收数据 result = self.recv(1024) print(result) # 实现handle_error回调函数 def handle_error(self): # 编写处理错误方法 t, e, trace = sys.exc_info() # 实现handle_close回调函数 def handle_close(self): print("连接关闭") self.close() # 创建对象并且执行asyncore.loop 进入循环 if __name__ == '__main__': client = scoket_client('127.0.0.1', 9000) # 开始启动运行循环 asyncore.loop(timeout=5) ...

5 min · 2351 words · Luenci

SQL性能调优

原文链接:https://blog.csdn.net/u010520146/article/details/81161762 一.创建索引 1.要尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引 2.1在经常需要进行检索的字段上创建索引,比如要按照表字段username进行检索,那么就应该在姓名字段上创建索引,如果经常要按照员工部门和员工岗位级别进行检索,那么就应该在员工部门和员工岗位级别这两个字段上创建索引。 2.2创建索引给检索带来的性能提升往往是巨大的,因此在发现检索速度过慢的时候应该首先想到的就是创建索引。 2.3一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有 必要。索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。 二.避免在索引上使用计算 在where字句中,如果索引列是计算或者函数的一部分,DBMS的优化器将不会使用索引而使用全表查询,函数 属于计算的一种,同时在in和exists中通常情况下使用EXISTS,因为in不走索引。 效率低: select * from user where salary*22 > 11000 (salary是索引列) ...

6 min · 2849 words · Luenci

Vue.js的基本知识

Vue.js概念 Vue.js 是目前最火的一个前端框架,React是最流行的一个前端框架(React除了开发网站,还可以开发手机App,Vue语法也是可以用于进行手机App开发的,需要借助于Weex) Vue.js 是前端的主流框架之一,和Angularjs、Reactjs一起,并成为前端三大主流框架!· Vue.js 是一套构建用户界面的框架,只关注视图层,它不仅易于上手,还便于与第三方库或既有项目整合。(Vue有配套的第三方类库,可以整合起来做大型项目的开发) 框架和库的区别 框架:是一套完整的解决方案;对项目的侵入性较大,项目如果需要更换框架,则需要重新架构整个项目。 库(插件):提供某一个小功能,对项目的侵入性较小,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求。 后端中的MVC与前端中的MVVM之间的区别 MVC是后端的分层开发概念; MVVM是前端视图层的概念,主要关注于视图层分离,也就是说:MVVM把前端的视图层,分为了三部分Model,View,VM ,ViewModel ...

14 min · 6761 words · Luenci