python菜鸟日记8

1. python中的多进程编程概念:由于Python是跨平台的,自然也应该提供一个跨平台的多进程支持。multiprocessing模块就是跨平台版本的多进程模块。multiprocessing模块提供了一个Process类来代表一个进程对象。

2. python中的多线程编程具体做法:当我们引入该multiprocessing模块后,对需要进行调用的函数创建进程:b= Process(target=函数名, args=(实参,)),因为process是一个类,所以b就是一个target函数的进程对象,我们也可以在里面添加name属性进行定义这个进程的名字,但python一般都是自动给这个进程一个名字,b.start()通过调用start()函数进行启动进程来执行函数,p.join()通过调用join()函数来说明当需要调用执行的函数调用完毕以后紧接着执行后面的语句代码,这个函数的左右就好像一个承接作用。

3. python中的进程池:如果需要对一个函数进行传入多个不同的实参,可以通过进程池来创建多个子进程。具体做法:from multiprocessing import Pool先引入进程池,b= Pool(n)创建进程池对象,里面的n表示可以同时进行n个进程,一定要记住多进程调用时,进程之间是交替执行的,b.apply_async(函数名, args=(实参,))创建进程,多次调用apply_async()创建多个子进程,p.close()多进程执行完毕后通过调用close()来结束进程并表示不能继续添加新的Process了,p.join()承接作用。

4. Process之间肯定是需要通信的,操作系统提供了很多机制来实现进程间的通信。Python的multiprocessing模块包装了底层的机制,提供了Queue、Pipes等多种方式来交换数据,以Queue为例,我们可以写两个函数,一个是read函数,一个是write函数,引入Queue以后,我们b=Queue()来创建一个b队列对象,然后在read函数中用a=b.get(true)来取出队列b中的值,在write函数中通过b.put(value)将value写入队列b中,这样以后,我们再创建俩个进程,然后start()调用执行,这俩个进程之间就可以用Queue来进行通信了。

5. 在Unix/Linux下,可以使用fork()调用实现多进程。要实现跨平台的多进程,可以使用multiprocessing模块。进程间通信是通过Queue、Pipes等实现的。

6. python中的多线程编程:Python的标准库提供了两个模块:_thread和threading,_thread是低级模块,threading是高级模块,对_thread进行了封装。绝大多数情况下,我们只需要使用threading这个高级模块

7. python中的多进程编程做法:与多进程编程类似,b= threading.Thread(target=函数名, name=线程别名),t.start()启动线程执行函数,t.join()承接作用

8. 多线程和多进程最大的不同在于,多进程中,同一个变量,各自有一份拷贝存在于每个进程中,互不影响,而多线程中,所有变量都由所有线程共享,所以任何一个变量都可以被任何一个线程修改,因此,线程之间共享数据最大的危险在于多个线程同时改一个变量,把内容给改乱了。(这里的变量指的是模块中的全局变量)

9. 多线程中的lock,b= threading.Lock()来创建锁对象b,对于与全局变量有关的函数中定义锁机制lock.acquire(),也就是多线程在执行这个函数时都要先得到这个锁,然后才能进行下面的语句代码,否则进入排队队列进行等待,执行完函数后lock.release()来进行释放锁,给等待队列中的线程继续执行,这样就避免了线程在交替执行时全局变量的不稳定性。

10. 多线程编程,模型复杂,容易发生冲突,必须用锁加以隔离,同时,又要小心死锁的发生。Python解释器由于设计时有GIL全局锁,导致了多线程无法利用多核。多线程的并发在Python中就是一个美丽的梦。

11. 在多线程环境下,每个线程都有自己的数据。一个线程使用自己的局部变量比使用全局变量好,因为局部变量只有线程自己能看见,不会影响其他线程,而全局变量的修改必须加锁。前面我们已经直到用lock进行多线程中的全局变量进行加锁,但是,python有提供了另一种方法,可以对全局变量不加锁,单个线程里的"全局变量",就是线程里的所有函数都可访问,但其它线程无法访问的变量...它叫做Threadlocal。

12.Threadloca的使用方法:我们通过b= threading.local()来创建b全局变量,而b又是一个ThreadLocal对象,在各个函数中可以定义b.a,b.c,b.e这些线程中的局部变量,是b的属性,就好像b是线程的全局变量,后面的b.a,b.e是线程的全局子变量,我们可以把他们全部看成是某个线程的全局变量,这样在多线程交替执行的时候,每个线程都能用自己的全局变量,就避免了源程序中的全局变量共享的问题。

13. 首先,要实现多任务,通常我们会设计Master-Worker模式,Master负责分配任务,Worker负责执行任务,因此,多任务环境下,通常是一个Master,多个Worker。如果用多进程实现Master-Worker,主进程就是Master,其他进程就是Worker。如果用多线程实现Master-Worker,主线程就是Master,其他线程就是Worker。

14. 多进程优缺点:多进程模式最大的优点就是稳定性高,因为一个子进程崩溃了,不会影响主进程和其他子进程。(当然主进程挂了所有进程就全挂了,但是Master进程只负责分配任务,挂掉的概率低)

多进程模式的缺点是创建进程的代价大,在Unix/Linux系统下,用fork调用还行,在Windows下创建进程开销巨大。另外,操作系统能同时运行的进程数也是有限的,在内存和CPU的限制下,如果有几千个进程同时运行,操作系统连调度都会成问题

15. 多线程优缺点:多线程模式通常比多进程快一点,但是也快不到哪去,而且,多线程模式致命的缺点就是任何一个线程挂掉都可能直接造成整个进程崩溃,因为所有线程共享进程的内存。在Windows上,如果一个线程执行的代码出了问题,你经常可以看到这样的提示:“该程序执行了非法操作,即将关闭”,其实往往是某个线程出了问题,但是操作系统会强制结束整个进程。在Windows下,多线程的效率比多进程要高。

16. 无论是多进程还是多线程,只要数量一多,效率肯定上不去,为什么呢?因为多线程多进程是交替执行的,所以会有切换过程,这个切换过程虽然很快,但是也需要耗费时间。如果有几千个任务同时进行,操作系统可能就主要忙着切换任务,根本没有多少时间去执行任务了,这种情况最常见的就是硬盘狂响,点窗口无反应,系统处于假死状态。所以,多任务一旦多到一个限度,就会消耗掉系统所有的资源,结果效率急剧下降,所有任务都做不好。

17. 计算密集型任务:计算密集型任务的特点是要进行大量的计算,消耗CPU资源,比如计算圆周率、对视频进行高清解码等等,全靠CPU的运算能力。这种计算密集型任务虽然也可以用多任务完成,但是任务越多,花在任务切换的时间就越多,CPU执行任务的效率就越低,所以,要最高效地利用CPU,计算密集型任务同时进行的数量应当等于CPU的核心数。计算密集型任务由于主要消耗CPU资源,因此,代码运行效率至关重要。Python这样的脚本语言运行效率很低,完全不适合计算密集型任务。对于计算密集型任务,最好用C语言编写。

18. IO密集型任务:涉及到网络、磁盘IO的任务都是IO密集型任务,这类任务的特点是CPU消耗很少,任务的大部分时间都在等待IO操作完成(因为IO的速度远远低于CPU和内存的速度)。对于IO密集型任务,任务越多,CPU效率越高,但也有一个限度。常见的大部分任务都是IO密集型任务,比如Web应用。IO密集型任务执行期间,99%的时间都花在IO上,花在CPU上的时间很少,因此,用运行速度极快的C语言替换用Python这样运行速度极低的脚本语言,完全无法提升运行效率。对于IO密集型任务,最合适的语言就是开发效率最高(代码量最少)的语言,脚本语言是首选,C语言最差

19. if __name__ == ‘__main__‘:的作用是:判断该模块是否是直接执行还是在被调用到另外一个模块中进行执行,

如果我们是直接执行某个.py文件的时候,该文件中那么”__name__ == ‘__main__‘“是True,但是我们如果从另外一个.py文件通过import导入该文件的时候,这时__name__的值就是我们这个py文件的名字而不是__main__。这个功能还有一个用处:调试代码的时候,在”if __name__ == ‘__main__‘“中加入一些我们的调试代码,我们可以让外部模块

调用的时候不执行我们的调试代码,但是如果我们想排查问题的时候,直接执行该模块文件,调试代码能够正常运行!

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-31 12:24:25

python菜鸟日记8的相关文章

python菜鸟日记2

1.对于类之间的的子类关系是可以传递的:比如C1是C2的子类,C2是C3的子类,那么C1也是C3的子类,任何类都可以看成是自身的子类,class类里面也可以嵌套一个class类 2.在类中,要想在函数中引用类的属性(全局变量),就必须使用完整名称(类名.变量名),而对于在类体中的语句,想引用类的属性,就必须使用属性的简单名称 例如: class c(): x=55 y=x+66                   --必须使用简单名称 def b(): f=c.x**3            

python菜鸟日记7

1. 如果直接在操作系统中进行命令行操作,那么一般使用的是操作系统所提供的接口函数,而如果想在python中也能够调用操作系统的接口函数来对文件,目录进行操作的话,可以使用os和os.path模块,这些模块可以直接调用操作系统提供的接口函数 2. >>>os.name ,name属性会反映出操作系统的一些信息,如果是posix,说明系统是Linux.Unix或Mac OS X,如果是nt,就是Windows系统,要获取详细的系统信息,可以调用uname()函数,注意uname()函数在W

python菜鸟日记4

1.在python中,0,'',{},(),[],空值,空列表,等等,都表示假值,反之都是真值在逻辑运算and,or中,返回的不是true或者false,返回的是逻辑运算符两边的其中一个值,而对于算数运算符, ==,!=,>,<,这些才返回的是true或者false 2.and,从左到右运算,当两边,都是真值时,返回最后一个真值,当两边都是假值时,就返回第一个假值,当同时存在真假值时,则返回第一个假值,其实,记法可根据逻辑运算结果记 例如: >>> 'a' and 'b' '

python菜鸟日记5

1.在python中我们可以导入模块,来调用模块里面的函数,在一个模块中,我们可以定义很多的函数和变量,但有些函数我们并不希望被别人使用,只希望在模块内部使用,那么,我们 可以通过_(下划线)前缀来实现,比如_ABC,_qiuhe,但是python并没有强制限制访问函数或变量,只是一种编程的习惯而已 2.在python中,pip是一个包管理工具,我们通过它来安装第三方软件的,一般来说,第三方库都会在Python官方的pypi.python.org网站注册,我们进入该网址,然后搜索我们要下载的模块

python菜鸟日记6

在函数调用的过程中,假设函数里面有循环嵌套的函数,那么在里面的函数遇到异常的时候,就终止函数,后面的语句将不会执行,而try后面的语句也将会中止执行,转而except. 异常其实也是一个类,是一个对象 此外,如果没有错误发生,可以在except语句块后面加一个else,当有错误发生时,会自动执行else语句 Python所有的错误都是从BaseException类派生的,常见的错误类型和继承关系看这里 使用try-except捕获错误还有一个巨大的好处,就是可以跨越多层调用,也就是说,不需要在每

Python菜鸟晋级03----repr() 与str() 函数的区别

两者均是将数值转换成字符串的形式,但是有细微的区别 str()会创建一个适合人阅读的字符串. repr()会创建适合解释器阅读的字符串. >>> hello = 'hello, world\n' >>> hellos = repr(hello) >>> hellos "'hello, world\\n'" #出现反斜杠进行转意 >>> hellos=str(hello) >>> hellos 'h

Python菜鸟晋级06----特殊属性整理

Python一切皆对象(object),每个对象都可能有多个属性(attribute). #现在我们来总结下所有的系统定义属性和方法, 先来看下保留属性: >>> Class1.__doc__ # 类型帮助信息 'Class1 Doc.' >>> Class1.__name__ # 类型名称 'Class1' >>> Class1.__module__ # 类型所在模块 '__main__' >>> Class1.__bases__

Python菜鸟之路:Django 路由补充FBV和CBV

在Python菜鸟之路:Django 路由.模板.Model(ORM)一节中,已经介绍了几种路由的写法及对应关系,那种写法可以称之为FBV: function base view . 今天补充另外一种路由关系的写法:CBV,即:class base view , 也可以看做为面向资源编程的另外一种叫法,类似tornado中的路由写法. 1. 建立路由关系urls.py from app01 import views urlpatterns = [ url(r'^home/', views.Hom

Python菜鸟晋级08----str.format()方法

用法 str.format()方法会返回一个新的字符串,在新的字符串中,原字符串的替换字段(大括号中和数字是预留的替换字段)被format方法中的参数代替. 替换字段被format方法中参数代替有一下集中形式------------------------- 按照位置 '{0},{1}'.format('kzc',18) #按照替换字段中的数字带入format方法中的参数 'kzc,18' '{},{}'.format('kzc',18) #替换字段中没有数字就按照顺序带入format方法中的参