为了账号安全,请及时绑定邮箱和手机立即绑定

Python 之网络式编程 (中)

标签:
Python

 九 利用socketserver实现并发

基于TCP服务端:

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import socketserver 4  5  6 class MyServer(socketserver.BaseRequestHandler): 7     def handle(self): 8         print('conn is:', self.request)  # <==>conn 9         print('addr is:', self.client_address)  # <==> addr10         while True:11             try:12                 # 收消息13                 data = self.request.recv(1024)14                 if not data:break15                 print('收到客户端的消息是', data)16                 # 发消息17                 self.request.sendall(data.upper())18             except Exception as EX:19                 print('错误提示:',EX)20                 break21 22 23 if __name__ == '__main__':24     s = socketserver.ThreadingTCPServer(('127.0.0.1', 8080), MyServer)  # 多线程;第一个参数,地址+端口;第二个参数,类
25   # s = socketserver.ForkingTCPServer(('127.0.0.1', 8080), MyServer)  # 多进程;多进程的开销大于多线程
26     s.serve_forever()

复制代码

基于TCP客户端:

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 from socket import * 4 ip_port = ('127.0.0.1', 8080) 5 back_log = 5 6 buffer_size = 1024 7 tcp_client = socket(AF_INET, SOCK_STREAM) 8 tcp_client.connect(ip_port) 9 while True:10     msg = input('>>').strip()11     if not msg:continue12     if msg == 'quit':break13     tcp_client.send(msg.encode('utf-8'))14     data = tcp_client.recv(buffer_size)15     print('收到服务端发来的消息:', data.decode('utf-8'))16 tcp_client.close()

复制代码

基于UDP服务端 

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import socketserver 4  5  6 class MyServer(socketserver.BaseRequestHandler): 7     def handle(self): 8         print(self.request) 9         print('收到客户端的消息是:', self.request[0].upper())10         self.request[1].sendto(self.request[0].upper(), self.client_address)11 12 13 if __name__ == '__main__':14     s = socketserver.ThreadingUDPServer(('127.0.0.1', 8080), MyServer)  # 第一个参数,地址+端口;第二个参数,类15     s.serve_forever()

复制代码

基于UDP客户端

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 from socket import * 4 ip_port = ('127.0.0.1', 8080) 5 buffer_size = 1024 6 udp_client = socket(AF_INET, SOCK_DGRAM)  # SOCK_DGRAM:数据报式套接字 7 while True: 8     msg = input('>>').strip() 9     udp_client.sendto(msg.encode('utf-8'), ip_port)10     data, addr = udp_client.recvfrom(buffer_size)11     print(data.decode('utf-8'))12     print(addr)

复制代码

 十 认证客户端的合法性

  如果想在分布式系统中实现一个简单的客户端链接认证功能,又不像SSL那么复杂,那么可以利用hmac+加盐的方法来实现。

复制代码

 1 # _*_coding:utf-8_*_ 2 __author__ = 'Linhaifeng' 3 from socket import * 4 import hmac, os 5  6 secret_key = b'alex bang bang bang' 7  8  9 def conn_auth(conn):10     '''11     认证客户端链接12     :param conn:13     :return:14     '''15     print('开始验证新链接的合法性')16     msg = os.urandom(32)  # 随机生成的;b'\xa3\x9d\xaa\x94\x9e\x89\xe9\xc9\xc3r\xf9E\xe0w\x82=\xaac-\x04\xd8:\xea\x07\xad\x1dx\x1er\xe0\x7f\x02'17     conn.sendall(msg)18     h = hmac.new(secret_key, msg)  # <hmac.HMAC object at 0x000000D5DA4824E0>19     digest = h.digest()  # 随机生成的;b'\x17!*\xae6\x81\xfe|)\x138\xfa2o%\x1a'20     respone = conn.recv(len(digest))21     return hmac.compare_digest(respone, digest)  # 比较第一个参数和第二个参数;相同,返回True,反之也成立22 23 24 def data_handler(conn, bufsize=1024):25     if not conn_auth(conn):26         print('该链接不合法,关闭')27         conn.close()28         return29     print('链接合法,开始通信')30     while True:31         data = conn.recv(bufsize)32         if not data: break33         conn.sendall(data.upper())34 35 36 def server_handler(ip_port, bufsize, backlog=5):37     '''38     只处理链接39     :param ip_port:40     :return:41     '''42     tcp_socket_server = socket(AF_INET, SOCK_STREAM)43     tcp_socket_server.bind(ip_port)44     tcp_socket_server.listen(backlog)45     while True:46         conn, addr = tcp_socket_server.accept()47         print('新连接[%s:%s]' % (addr[0], addr[1]))48         data_handler(conn, bufsize)49 50 51 if __name__ == '__main__':52     ip_port = ('127.0.0.1', 9999)53     bufsize = 102454     server_handler(ip_port, bufsize)

复制代码

服务端

复制代码

 1 # _*_coding:utf-8_*_ 2 __author__ = 'Linhaifeng' 3 from socket import * 4 import hmac, os 5  6 secret_key = b'alex bang bang bang' 7  8  9 def conn_auth(conn):10     '''11     认证客户端链接12     :param conn:13     :return:14     '''15     print('开始验证新链接的合法性')16     msg = os.urandom(32)17     conn.sendall(msg)18     h = hmac.new(secret_key, msg)19     digest = h.digest()20     respone = conn.recv(len(digest))21     return hmac.compare_digest(respone, digest)22 23 24 def data_handler(conn, bufsize=1024):25     if not conn_auth(conn):26         print('该链接不合法,关闭')27         conn.close()28         return29     print('链接合法,开始通信')30     while True:31         data = conn.recv(bufsize)32         if not data: break33         conn.sendall(data.upper())34 35 36 def server_handler(ip_port, bufsize, backlog=5):37     '''38     只处理链接39     :param ip_port:40     :return:41     '''42     tcp_socket_server = socket(AF_INET, SOCK_STREAM)43     tcp_socket_server.bind(ip_port)44     tcp_socket_server.listen(backlog)45     while True:46         conn, addr = tcp_socket_server.accept()47         print('新连接[%s:%s]' % (addr[0], addr[1]))48         data_handler(conn, bufsize)49 50 51 if __name__ == '__main__':52     ip_port = ('127.0.0.1', 9999)53     bufsize = 102454     server_handler(ip_port, bufsize)

复制代码

客户端(合法,其他均为非法)

 十一 FTP服务器

实现如下功能:

  1、用户加密认证

  2、每个用户都有自己的家目录,且只能访问自己的家目录

  3、允许用户在ftp server上随意切换目录(cd)

  4、允许用户查看当前目录下的所有文件(ls)

  5、允许上传和下载文件

  6、文件传输过程中显示进度条

  7、支持文件的断点续传

ftp server

目录结构:

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import os,sys 4 PATH = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) 5 sys.path.append(PATH) 6  7  8 from core import main 9 10 11 if __name__ == '__main__':12     main.ArgvHandler()

复制代码

ftp_server.py

复制代码

1 [DEFAULT]2 3 [alex]4 Password =1235 Quotation = 1006 7 [root]8 Password = root9 Quotation = 100

复制代码

accounts.cfg

复制代码

1 #!/usr/bin/env python2 # -*- coding:utf-8 -*-3 import os4 BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))5 6 ip = '127.0.0.1'7 port = 80808 9 ACCOUNT_PATH = os.path.join(BASE_DIR, 'conf', 'accounts.cfg')

复制代码

settings.py

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import socketserver 4 import optparse 5 import socketserver 6 from conf import settings 7 from core import server 8  9 10 class ArgvHandler():11     def __init__(self):12         self.op = optparse.OptionParser()13         # self.op.add_option('-s', '--server', dest='server')14         # self.op.add_option('-P', '--port', dest='port')15         options, args = self.op.parse_args()16         # print(options)  # {'server': '127.0.0.1', 'port': '8080'}17         # print(type(options))  # <class 'optparse.Values'>18         # print(options.server)  # 127.0.0.119         # print(args)20 21         options, args = self.op.parse_args()22         self.verify_args(options, args)23 24     def verify_args(self, options, args):25         cmd = args[0]26         # 第一种方法27         # if cmd == 'start':28         #     pass29         # else:30         #     pass31         # 第二种方法32         if hasattr(self, cmd):33             func = getattr(self, cmd)34             func()35 36     def start(self):37         print('ths server is working...')38         s = socketserver.ThreadingTCPServer((settings.ip, settings.port), server.ServerHandler)39         s.serve_forever()40 41     def help(self):42         pass

复制代码

main.py

复制代码

  1 #!/usr/bin/env python  2 # -*- coding:utf-8 -*-  3 import socketserver  4 import json  5 import configparser  6 from conf import settings  7 import os  8   9 STATUS_CODE = { 10     250: "Invalid cmd format,e.g:{'action':'get','filename':'test.py','size':344}", 11     251: "Invalid cmd", 12     252: "Invalid auth data", 13     253: "Wrong username or password", 14     254: "Passed authentication", 15     255: "Filename doesn't provided", 16     256: "File doesn't exist on server", 17     257: "ready to send file", 18     258: "md5 verification", 19     800: "the file exist,but not enough,is continue?", 20     801: "the file exist!", 21     802: "ready to receive datas", 22     900: "md5 valdate success" 23 } 24  25  26 class ServerHandler(socketserver.BaseRequestHandler): 27     def handle(self): 28         while True: 29             data = self.request.recv(1024).strip()  # self.request=conn 30             data = json.loads(data.decode('utf8')) 31             if data.get('action'): 32                 if hasattr(self, data.get('action')): 33                     func = getattr(self, data.get('action')) 34                     func(**data) 35                 else: 36                     print('Invalid cmd') 37             else: 38                 print('Invalid cmd') 39  40     def send_response(self, status_code): 41         response = {'status_code': status_code} 42         self.request.sendall(json.dumps(response).encode('utf8')) 43  44     def auth(self, **data): 45         username = data['username'] 46         password = data['password'] 47         username = self.authenticate(username, password) 48         if username: 49             self.send_response(254) 50         else: 51             self.send_response(253) 52  53     def authenticate(self, username, password): 54         cfg = configparser.ConfigParser() 55         cfg.read(settings.ACCOUNT_PATH) 56         if username in cfg.sections(): 57             if cfg[username]['Password'] == password: 58                 self.username = username 59                 self.mainPath = os.path.join(settings.BASE_DIR, 'home', self.username) 60                 print('passed authenticate') 61                 return username 62  63     def put(self, **data): 64         print('data', data) 65         file_name = data.get('file_name') 66         file_size = data.get('file_size') 67         target_path = data.get('target_path') 68         abs_path = os.path.join(self.mainPath, target_path, file_name) 69         has_received = 0 70         if os.path.exists(abs_path): 71             file_has_size = os.stat(abs_path).st_size 72             if file_has_size < file_size: 73                 # 断点续传 74                 self.request.sendall('800'.encode('utf8')) 75                 choice = self.request.recv(1024).decode('utf8') 76                 if choice == 'Y': 77                     self.request.sendall(str(file_has_size).encode('utf8')) 78                     has_received = file_has_size 79                     f = open(abs_path, 'ab') 80                 else: 81                     f = open(abs_path, 'wb') 82             else: 83                 # 文件完全存在 84                 self.request.sendall('801'.encode('utf8')) 85                 return 86         else: 87             self.request.sendall('802'.encode('utf8')) 88             f = open(abs_path, 'wb') 89  90         while has_received < file_size: 91             try: 92                 data = self.request.recv(1024) 93             except Exception as EX: 94                 break 95             f.write(data) 96             has_received += len(data) 97         f.close() 98  99     def ls(self, **data):100         file_list = os.listdir(self.mainPath)101         file_str = '\n'.join(file_list)102         if not len(file_list):103             file_str = '<empty dir>'104         self.request.sendall(file_str.encode('utf8'))105 106     def cd(self, **data):107         dirname = data.get('dirname')108         if dirname == '..':109             self.mainPath = os.path.dirname(self.mainPath)110         else:111             self.mainPath = os.path.join(self.mainPath, dirname)112         self.request.sendall(self.mainPath.encode('utf8'))113 114     def mkdir(self, **data):115         dirname = data.get('dirname')116         path = os.path.join(self.mainPath, dirname)117         if not os.path.exists(path):118             if '/' in path:119                 os.makedirs(path)120             else:121                 os.mkdir(path)122             self.request.sendall('create success'.encode('utf8'))123         else:124             self.request.sendall('dirname exist'.encode('utf8'))

复制代码

server.py

ftp client

目录结构

复制代码

  1 #!/usr/bin/env python  2 # -*- coding:utf-8 -*-  3 # import socket  4 #  5 # sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  6 # sk.connect(('127.0.0.1', 8080))  7 import optparse  8 import socket  9 import json 10 import os, sys 11 STATUS_CODE = { 12     250: "Invalid cmd format,e.g:{'action':'get','filename':'test.py','size':344}", 13     251: "Invalid cmd", 14     252: "Invalid auth data", 15     253: "Wrong username or password", 16     254: "Passed authentication", 17     255: "Filename doesn't provided", 18     256: "File doesn't exist on server", 19     257: "ready to send file", 20     258: "md5 verification", 21     800: "the file exist,but not enough,is continue?", 22     801: "the file exist!", 23     802: "ready to receive datas", 24     900: "md5 valdate success" 25 } 26  27  28 class ClientHandler(object): 29     def __init__(self): 30         self.op = optparse.OptionParser() 31         self.op.add_option('-s', '--server', dest='server') 32         self.op.add_option('-P', '--port', dest='port') 33         self.op.add_option('-u', '--username', dest='username') 34         self.op.add_option('-p', '--password', dest='password') 35  36         self.options, self.args = self.op.parse_args() 37  38         self.verify_args(self.options, self.args) 39         self.make_connection() 40         self.mainPath = os.path.dirname(os.path.abspath(__file__)) 41         self.last = 0 42  43     def verify_args(self, options, args): 44         server = options.server 45         port = options.port 46         username = options.username 47         password = options.password 48         if int(port) > 0 and int(port) < 65535: 49             return True 50         else: 51             exit('the port is in 0-65535') 52  53     def make_connection(self): 54         self.sock = socket.socket() 55         self.sock.connect((self.options.server, int(self.options.port))) 56  57     def interactive(self): 58         print('begin to interactive...') 59         # self.authenticate() 60         if self.authenticate(): 61             while 1: 62                 cmd_info = input('[%s]' % self.current_dir).strip() 63                 cmd_list = cmd_info.split() 64                 if hasattr(self, cmd_list[0]): 65                     func = getattr(self, cmd_list[0]) 66                     func(*cmd_list) 67  68     def put(self, *cmd_list): 69         # put 12.png images 70         actions, local_path, target_path = cmd_list 71         local_path = os.path.join(self.mainPath, local_path) 72         file_name = os.path.basename(local_path) 73         file_size = os.stat(local_path).st_size 74         data = { 75             'action': 'put', 76             'file_name': file_name, 77             'file_size': file_size, 78             'target_path': target_path 79         } 80         self.sock.send(json.dumps(data).encode('utf8')) 81         is_exist = self.sock.recv(1024).decode('utf8') 82         has_send = 0 83         if is_exist == '800': 84             # 文件不完整 85             choice = input('the file exist,but not enough,is continue?[Y/N]').strip() 86             if choice.upper() == 'Y': 87                 self.sock.sendall('Y'.encode('utf8')) 88                 continue_position = self.sock.recv(1024).decode('utf8') 89                 has_send += int(continue_position) 90             else: 91                 self.sock.sendall('N'.encode('utf8')) 92         elif is_exist == '801': 93             # 文件完全存在 94             print('the file exist') 95             return 96         else: 97             pass 98         f = open(local_path, 'rb') 99         f.seek(has_send)100         while has_send < file_size:101             data = f.read(1024)102             self.sock.sendall(data)103             has_send += len(data)104             self.show_progress(has_send, file_size)105         f.close()106         print('successfully upload!')107 108     def show_progress(self, has, total):109         rate = float(has)/float(total)110         rate_num = int(rate*100)111         if self.last != rate_num:112             sys.stdout.write('%s%% %s\r' % (rate_num, '#'*rate_num))113         self.last = rate_num114 115     def ls(self, *cmd_list):116         data = {117             'action': 'ls'118         }119         self.sock.sendall(json.dumps(data).encode('utf8'))120         data = self.sock.recv(1024).decode('utf8')121         print(data)122 123     def cd(self, *cmd_list):124         data = {125             'action': 'cd',126             'dirname': cmd_list[1]127         }128         self.sock.sendall(json.dumps(data).encode('utf8'))129         data = self.sock.recv(1024).decode('utf8')130         self.current_dir = os.path.basename(data)131 132     def mkdir(self, *cmd_list):133         data = {134             'action': 'mkdir',135             'dirname': cmd_list[1]136         }137         self.sock.sendall(json.dumps(data).encode('utf8'))138         data = self.sock.recv(1024).decode('utf8')139 140     def authenticate(self):141         if self.options.username is None or self.options.password is None:142             username = input('username:')143             password = input('password:')144             return self.get_auth_result(username, password)145         return self.get_auth_result(self.options.username, self.options.password)146 147     def response(self):148         data = self.sock.recv(1024).decode('utf8')149         data = json.loads(data)150         return data151 152     def get_auth_result(self, username, password):153         data = {154             'action': "auth",155             'username': username,156             'password': password157         }158         self.sock.send(json.dumps(data).encode('utf8'))159         response = self.response()160         print('response:', response['status_code'])161         if response['status_code'] == 254:162             self.username = username163             self.current_dir = username164             print(STATUS_CODE[response['status_code']])165             return True166         else:167             print(STATUS_CODE[response['status_code']])168 169 170 ch = ClientHandler()171 ch.interactive()

复制代码

ftp_client.py

 十二 进程与线程

1、为什么要有操作系统?

  现代计算机系统是由一个或者多个处理器、内存、硬盘、打印机、键盘、鼠标和显示器等组成的。网络接口以及各种其他输入/输出设备组成的复杂系统,每位程序员不可能掌握所有系统实现的细节,并且管理优化这些部件是一件具有挑战性极强的工作。所以,我们需要为计算机安装一层软件,成为操作系统,任务就是用户程序性提供一个简单清晰的计算机模型,并管理以上设备。

  定义:操作系统是一个用来协调、管理和控制计算机硬件和软件资源的系统程序,它位于硬件和应用程序之间。程序是运行在系统上的具有某种功能的软件,比如:浏览器,音乐播放器等。

  操作系统内部的定义:操作系统的内核是一个管理和控制程序,负责管理计算机的所有物理资源,其中包括:文件系统、内存管理、设备管理、进程管理。

2、什么是进程?

  假如有两个程序A和B,程序A在执行到一半的过程中,需要读取大量的数据输入(I/O操作),而此时CPU只能静静地等待任务A读取完数据才能继续执行,这样就白白浪费了CPU资源。是不是在程序A读取数据的过程中,让程序B去执行,当程序A读取完数据之后,让程序B暂停,然后让程序A继续执行?当然没问题,但这里有一个关键词:切换;既然是切换,那么这就涉及到了状态的保存,状态的恢复,加上程序A与程序B所需要的系统资源(内存,硬盘,键盘等等)是不一样的。自然而然的就需要有一个东西去记录程序A和程序B分别需要什么资源,怎样去识别程序A和程序B等等,所以就有了一个叫进程的抽象。

定义:

  进程就是一个程序在一个数据集上的一次动态执行过程。进程一般由程序、数据库、进程控制块三部分组成。我们编写的程序用来描述进程要完成哪些功能以及如何完成。数据集则是程序在执行过程中所需要使用的资源。进程控制块用来记录的外部特征,描述进程的执行变化过程,系统可以利用它来控制和管理进程,它是系统感知进程存在的唯一标志。

  本质上就是一段程序的运行过程(抽象的概念)

3、什么是线程?

  线程的出现是为了降低上下文切换的消耗,提高系统的并发性,并突破一个进程只能干一样事的缺陷,让进程内并发成为可能。

4、进程与线程区别

1、一个程序至少有一个进程,一个进程至少有一个线程(进程可以理解成线程的容器)

2、进程在执行过程中拥有独立的内存单元,而多个线程共享内存,从而极大地提高了程序的运行效率

3、线程在执行过程中与进程还是有区别的,每个独立的线程有一个程序运行的入口,顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。

4、进程是具有一定独立功能的程序关于某个数据集合上的一次运行活动,进程是系统进行资源分配和调度的一个独立单位;线程是进程的一个实体,是CPU调度和分源的基本单位,它是比进程更小的能独立运行的基本单位,线程自己基本上不拥有系统资源,只拥有一点运行中必不可少的资源(如程序计数器,一组寄存器和钱),但是它可与同属一个进程的其他的线程共享进程所拥有的全部资源。一个进程可以创建和撤销另一个线程;同一个进程中的多个线程之间可以并发执行。

5、线程:最小的执行单元(实例);进程:最小的资源单位

5、Python的GIL(全局解释锁;Global Interpreter Lock)

  In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

上面的核心意思:无论你启多少个线程,你有多少个CPU,Python在执行的时候会淡定的在同一时刻只允许一个线程运行。

6、 线程的两种调用方式

  threading 模块建立在thread 模块之上。thread模块以低级、原始的方式来处理和控制线程,而threading 模块通过对thread进行二次封装,提供了更方便的api来处理线程。

调用方式:

方式一、

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import threading 4 import time 5  6  7 def music(): 8     print('begin to listen % s' % time.ctime()) 9     time.sleep(3)10     print('stop to listen %s' % time.ctime())11 12 13 def game():14     print('begin to play game % s \r\n' % time.ctime())15     time.sleep(5)16     print('stop to play game %s \r\n' % time.ctime())17 18 19 threads = []20 t1 = threading.Thread(target=music)21 t2 = threading.Thread(target=game)22 threads.append(t1)23 threads.append(t2)24 if __name__ == '__main__':25     # join()功能:在子线程完成运行之前,这个子线程的父线程讲一直被阻塞26     # t1 = threading.Thread(target=music)27     # t2 = threading.Thread(target=game)28     # t1.start()29     # t2.start()30     #31     # t1.join()32     # t2.join()33     # print('end')34     35     # setDaemon():将线程生命为守护线程36     t2.setDaemon(True)  # 注:一定要在start之前设置37     for t in threads:38         t.start()39     print('end')

复制代码

threading

方式二、

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import threading 4 import time 5  6  7 class MyThread(threading.Thread): 8     def __init__(self, num): 9         threading.Thread.__init__(self)10         self.num = num11 12     def run(self):  # 定义每个线程要运行的函数13 14         print("running on number:%s" % self.num)15 16         time.sleep(3)17 18 19 if __name__ == '__main__':20     t1 = MyThread(1)21     t2 = MyThread(2)22     t1.start()23     t2.start()24 25     print("ending......")

复制代码

继承方式调用线程

join():在子线程完成运行之前,这个子线程的父线程将一直被阻塞。

setDaemon(True):

  将线程生命为守护线程,必须在start()方法调用之前设置,如果不设置为守护线程,程序会被无限挂起。这个方法基本和join是相反的。当我们在程序运行中,执行一个主线程,如果主线程又创建一个子线程,主线程和子线程就分兵两路,分别运行,那么当主线程完成想退出时,会验证子线程是否完成。如果子线程未完成,则主线程会等待子线程完成后再退出。但是有时候我们需要的是,只要主线程完成了,不管子线程是否完成,都要和主线程一起退出,这时就可以用setDaemon方法了。

 其他方法:

复制代码

 1 # run():用于表示线程活动的方法 2 # start():启动线程活动 3 # isAlive():返回线程是否活动的,返回布尔值,True/False 4 # getName():返回线程名字 5 # setName():设置线程名字 6  7 threading模块提供的一些方法: 8 # threading.currentThread():返回当前的线程变量 9 # threading.enumerate():返回一个包含正在运行的线程的list。正在运行指线程启动后-结束前,不包括启动前和终止后的线程10 # threading.activeCount():返回正在运行的线程数量,与len(threading.enumerate())有相同的结果

复制代码

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import threading 4 import time 5  6  7 def music(): 8     print('begin to listen % s' % time.ctime()) 9     time.sleep(3)10     print('stop to listen %s' % time.ctime())11 12 13 def game():14     print('begin to play game % s \r\n' % time.ctime())15     time.sleep(5)16     print('stop to play game %s \r\n' % time.ctime())17 18 19 threads = []20 t1 = threading.Thread(target=music)21 t2 = threading.Thread(target=game)22 threads.append(t1)23 threads.append(t2)24 if __name__ == '__main__':25     # join()功能:在子线程完成运行之前,这个子线程的父线程讲一直被阻塞26     # t1 = threading.Thread(target=music)27     # t2 = threading.Thread(target=game)28     # t1.start()29     # t2.start()30     #31     # t1.join()32     # t2.join()33     # print('end')34 35     # setDaemon():将线程生命为守护线程36     t2.setDaemon(True)  # 注:一定要在start之前设置37     for t in threads:38         t.start()39         print(t.getName())40         print('count:', threading.activeCount())41     while threading.activeCount() == 3:42         print('end')

复制代码

其他方法演示

7、同步锁(lock)

复制代码

 1 #!/usr/bin/env python 2 # -*- coding:utf-8 -*- 3 import threading 4 import time 5 num = 100 6  7  8 def sub(): 9     global num10     print('ok')11     lock.acquire()  # 加锁12     temp = num13     time.sleep(0.001)14     num = temp-115     lock.release()  # 释放锁16 17 18 li = []19 lock = threading.Lock()20 for i in range(100):21     t1 = threading.Thread(target=sub)22     t1.start()23     li.append(t1)24 for l in li:25     l.join()26 print(num)

复制代码

 注:多个线程都在同时操作同一个共享资源,所以造成了资源破坏(join会造成串行,失去线程的意义),可以通过同步锁来解决这种问题。

作者:陈彦斌

原文出处:https://www.cnblogs.com/chenyanbin/p/10406263.html  

Python 之网络式编程 (上):https://www.imooc.com/article/281284  

Python 之网络式编程 (下):https://www.imooc.com/article/281286  

点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消