首页 > 编程语言 >python基础day40

python基础day40

时间:2023-07-07 18:55:38浏览次数:35  
标签:__ 解释器 python 基础 print 线程 进程 import day40

GIL全局解释器锁

python在设计之初就考虑到在主循环中,同时只有一个线程在执行。

虽然 Python 解释器中可以“运行”多个线程,但在任意时刻只有一个线程在解释器中运行。

对Python虚拟机的访问由全局解释器锁(GIL)来控制,正是这个锁能保证同一时刻只有一个线
程在运行。

1. python代码运行在解释器之上,有解释器来翻译执行

2. python解释器的种类有哪些?
CPython IPython PyPy Jython

3. GIL锁存在于CPython解释器中

4. 市面上目前绝大多数(95%)都使用的是CPython解释器

5. 起一个垃圾回收线程,在起一个正常执行代码的线程,当垃圾回收线程还没回收完毕,其他线程有可能会抢夺资源,这种情况在python设计之处就不允许的

6. python在设计之处,就在python解释器之上加了一把锁(GIL锁),加这个锁的目的是:同一时刻只能有一个线程执行,不能同时有多个线程执行,如果开了多个线程,那么,线程要想有执行权限,必须先拿到这把锁(GIL锁)

只需要记住:同一时刻多个线程只能有一个线程在运行,其他线程都处于等待状态

理解记忆部分

1. python有GIL锁的原因,同一个进程下多个线程实际上同一时刻,只有一个线程在执行

2. 只有在python上开进程用的多,其他语言一般不开多进程,只开多线程就够了

3. cpython解释器开多线程不能利用多核优势,只有开多进程才能利用多核优势,其他语言不存在这个问题

4. 8核cpu电脑,充分利用起我这个8核,至少起8个线程(在8个进程中,每个进程中有一个线程),8条线程全是计算--->计算机cpu使用率是100%,

5. 如果不存在GIL锁,一个进程下,开启8个线程,它就能够充分利用cpu资源,跑满cpu

6. cpython解释器中好多代码,模块都是基于GIL锁机制写起来的,改不了了---》我们不能有8个核,但我现在只能用1核,----》开启多进程---》每个进程下开启的线程,可以被多个cpu调度执行

7. cpython解释器:io密集型使用多线程,计算密集型使用多进程

 

 io密集型,遇到io操作会切换cpu,假设你开了8个线程,8个线程都有io操作---》io操作不消耗cpu---》一段时间内看上去,其实8个线程都执行了, 选多线程好一些

计算密集型,消耗cpu,如果开了8个线程,第一个线程会一直占着cpu,而不会调度到其他线程执行,其他7个线程根本没执行,所以我们开8个进程,每个进程有一个线程,8个进程下的线程会被8个cpu执行,从而效率高

计算密集型选多进程好一些,在其他语言中,都是选择多线程,而不选择多进程

互斥锁

'''多个线程去操作同一个数据,会出现并发安全问题,怎么解决?加锁'''
from threading import Thread, Lock

n = 10

import time
def task(lock):
    lock.acquire() # 只要有一个线程进来了,其他线程都要等着
    global n
    # n -= 1
    temp = n
    time.sleep(0.1)
    n = temp - 1
    lock.release()


if __name__ == '__main__':
    lock = Lock()
    ll = []
    for i in range(10):
        t = Thread(target=task, args=(lock, ))
        t.start()
        ll.append(t)
    for j in ll:
        j.join()
    print('n:', n)

线程队列

# 进程之间的数据是隔离的,所以,我们使用了队列来实现了进程之间的通信

# 线程之间的数据是共享的,那么,我们为什么还使用队列呢?

"""
    队列的底层其实还是:管道 + 锁
    锁就是为了保证数据的安全
    线程内部使用队列,也是为了保证线程里的数据安全
"""

# 进程Queue用于父进程与子进程(或同一父进程中多个子进程)间数据传递
# python自己的多个进程间交换数据或者与其他语言(如Java)进程queue就无能为力

# queue.Queue 的缺点是它的实现涉及到多个锁和条件变量,因此可能会影响性能和内存效率。
'''只要加锁,必会影响性能和效率!但是好处就是保证数据的安全'''

# 线程队列的使用
1. 先进先出
import queue

q=queue.Queue()
q.put('first')
q.put('second')
q.put('third')

print(q.get())
print(q.get())
print(q.get())
2. 后进先出


# Lifo: last input first output
# q=queue.LifoQueue() # 得到一个对象,队列
# q.put('first')
# q.put('second')
# q.put('third')
# 
# print(q.get())
# print(q.get())
# print(q.get())

3. 优先级队列
import queue

q = queue.PriorityQueue()
# put进入一个元组,元组的第一个元素是优先级(通常是数字,也可以是非数字之间的比较),数字越小优先级越高
q.put(('a', 'a'))
q.put(('b', 'b'))
q.put(('c', 'c'))

print(q.get())
print(q.get())
print(q.get())
'''
结果(数字越小优先级越高,优先级高的优先出队):
(10, 'b')
(20, 'a')
(30, 'c')
'''

进程池和线程池

池子:容器,盛放多个元素值
进程池:存放多个进程的
线程池:存放多个线程的

"""
    进程池:提前定义一个池子,里面放很多个进程,只需要往池子里面丢任务即可,有这个池子里面的任意一个进程来执行任务.
    
    线程池:提前定义一个池子,里面放很多个线程,只需要往池子里面丢任务即可,有这个池子里面的任意一个线程来执行任务.
"""
# 例子
def task(n, m):
    return  n + m  # 1+2


def task1():
    # ...
    return {
        'username':'kevin',
        'password':123
    }

from multiprocessing import Process
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor


def callback(res):
    print(res.result())


def callback1(res):
    print(res.result())
    print(res.result()['username'])


if __name__ == '__main__':

    """开一个进程池,提前放进去多个进程"""
    # max_workers
    pool = ThreadPoolExecutor(2)  # 池子里面有5个工作者,其实就是实例化了5个进程

    # 有了进程池,我们现在往池子里面丢任务
    # pool.submit(task, 1, 2)
    # 进程池要主动调一个回调函数,来把结果给到我们
    # 回调函数需要我们自己提前写好
    pool.submit(task, n=1, m=2).add_done_callback(callback)
    # pool.submit(task1).add_done_callback(callback1)
    pool.shutdown()  # join + close
    print(123)

线程池爬取网页

import requests
from concurrent.futures import ThreadPoolExecutor,ProcessPoolExecutor

def get_page(url):
    res = requests.get(url)  # 爬取网页
    name = url.rsplit('/')[-1] + '.html'
    return {'name': name, 'text': res.content}


def call_back(fut):
    print(fut.result()['name'])
    with open(fut.result()['name'], 'wb') as f:
        f.write(fut.result()['text'])


if __name__ == '__main__':
    pool = ThreadPoolExecutor(2)
    urls = ['http://www.baidu.com', 'http://www.cnblogs.com', 'http://www.taobao.com']
    for url in urls:
        pool.submit(get_page, url).add_done_callback(call_back)
        
谈谈:解决高并发问题
linux:负载均衡

协程

进程:进程解决高并发问题

线程:解决高并发问题

协程:它是单线程下的并发,它是程序员级别的,我们来控制如何切换,什么时候切换
进程和线程是操作系统来控制的,我们控制不了

协程是一种用户态(程序员)的轻量级线程,即协程是由用户程序自己控制调度的。

进程的开销 >>>>>> 线程的开销 >>>>>> 协程的开销

# 协程的使用需要借助于第三方模块gevent模块
必须先安装: pip install gevent

 

协程实现高并发程序

# 服务端:
from gevent import monkey;

monkey.patch_all()
import gevent
from socket import socket
# from multiprocessing import Process
from threading import Thread


def talk(conn):
    while True:
        try:
            data = conn.recv(1024)
            if len(data) == 0: break
            print(data)
            conn.send(data.upper())
        except Exception as e:
            print(e)
    conn.close()


def server(ip, port):
    server = socket()
    server.bind((ip, port))
    server.listen(5)
    while True:
        conn, addr = server.accept()
        # t=Process(target=talk,args=(conn,))
        # t=Thread(target=talk,args=(conn,))
        # t.start()
        gevent.spawn(talk, conn)


if __name__ == '__main__':
    g1 = gevent.spawn(server, '127.0.0.1', 8080)
    g1.join()

# 客户端:
    import socket
from threading import current_thread, Thread


def socket_client():
    cli = socket.socket()
    cli.connect(('127.0.0.1', 8080))
    while True:
        ss = '%s say hello' % current_thread().getName()
        cli.send(ss.encode('utf-8'))
        data = cli.recv(1024)
        print(data)


for i in range(5000):
    t = Thread(target=socket_client)
    t.start()

 

标签:__,解释器,python,基础,print,线程,进程,import,day40
From: https://www.cnblogs.com/zfq132/p/17535833.html

相关文章

  • 第二节 Java基础语法
    day02-Java基础语法1.注释​ 注释是对代码的解释和说明文字。Java中的注释分为三种:单行注释://这是单行注释文字多行注释:/*这是多行注释文字这是多行注释文字这是多行注释文字*/注意:多行注释不能嵌套使用。文档注释(暂时用不到):/**这是多行注释文字这是......
  • python字典(二)- 嵌套
    1.字典列表alien_0={'color':'green','points':5}alien_1={'color':'yellow','points':10}alien_2={'color':'red','points':15}aliens=[alien_0,alien_1,alie......
  • Python 引用问题 - ImportError: attempted relative import with no known parent pa
    问题描述近日在尝试引用其他文件的代码时,遇到了错误:ImportError:attemptedrelativeimportwithnoknownparentpackage.问题大致是这样的:我想在code2.py中引用code1.py的函数,如from..folder1.code1importxxx,运行code2.py时出现错误。root├──folder1│......
  • python函数进阶
    Python函数进阶一、函数多返回值1.1多个返回值如果一个函数要有多个返回值,该如何书写代码?"""演示函数的多返回值示例"""#演示使用多个变量,接受多个返回值deftest_return():return1,"hello",Truex,y,z=test_return()print(x)#1print(y)#hello......
  • 爬虫第一天基础
    目录1前戏2爬虫介绍3requests模块介绍和快速使用4get请求携带参数5编码和解码6携带请求头7发送post请求,携带数据8携带cookie两种方式1前戏#介绍:使用requests可以模拟浏览器的请求,比起之前用到的urllib,requests模块的api更加便捷(本质就是封装了urllib3)#注意:requests库......
  • python multiprocessing库使用记录
    pythonmultiprocessing库使用记录需求是想并行调用形式化分析工具proverif,同时发起对多个query的分析(378个)。实验室有40核心80线程的服务器(双cpu,至强gold5218R*2)。观察到单个命令在分析时内存占用不大,且只使用单核心执行,因此考虑同时调用多个命令同时执行分析,加快结果输出。......
  • # Python_函数专题(一)
    目录函数基础基础函数调用参数返回值变量承接print定义函数定义函数的格式函数嵌套函数调用死循环函数参数单参数双参数报错指定参数类型函数文档注释函数返回值Return定义带有返回值的参数返回多个值函数基础基础函数的基础理论函数,即一段具有特定功能的代码块调用函数,即......
  • 如何利用 Python 自动发邮件,打工人福音
    在工作中,每天或者每周结束的时候我们都会发送相应的日报或者周报给上级领导,来汇报你做了那些工作,可是汇报工作内容的时候我们始终都是打开邮箱、写入内容,发送和抄送给固定的人,那么这么繁琐并且重复的一件事,我们能不能使用程序来简化?答案是可以的,接下来我们就使用Python来操作......
  • 等保测评基础知识
     网络安全等级保护 定义:是指对国家秘密信息、法人或其他组织及公民专有信息以及公开信息和存储、传输、处理这些信息的信息系统分等级实行安全保护,对信息系统中使用的安全产品实行按等级管理,对信息系统中发生的信息安全事件分等级进行响应、处置。等级保护,即分等级保护,分等级监......
  • 如何解决Shell执行python文件,传参空格引起的问题
    这篇文章给大家分享的是有关如何解决Shell执行python文件,传参空格引起的问题的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。使用shell调用一个python文件,并向shell中传入参数,举例如下:p1='wang'p2='shuang'pythonpy文件$p1$p2 这种情况可以......