Python学习笔记_Day018
2018-03-21 21:06
106 查看
今天结束了多线程与多进程的学习,开始进入网络编程的学习
一、多进程与多线程
1. 计算机行业遵循的三大定律
摩尔定律 - 每隔18月,硬件性能翻倍
安迪比尔定律 -
反摩尔定律 -
ps:貌似这个和多进程多线程没啥关系,不过还是可以了解了解2.如果多个任务之间没有任何的关联(独立子任务)而且希望利用cpu的多核特性,那么我们推荐使用多进程
import time import random from multiprocessing import Process # 如果多个任务之间没有任何的关联(独立子任务)而且希望利用cpu的多核特性 # 那么我们推荐使用多进程 # Information Technology # 摩尔定律 - 每隔18月,硬件性能翻倍 # 安迪比尔定律 - # 反摩尔定律 - def download(filename): print('开始下载%s...' % filename) delay = random.randint(5, 15) time.sleep(delay) print('%s下载完成, 用时%d秒' % (filename, delay)) def main(): start = time.time() p1 = Process(target=download, args=('Python从入门到住院.pdf',)) p1.start() p2 = Process(target=download, args=('Pekin Hot.avi',)) p2.start() p1.join() # 等待进程结束 p2.join() end = time.time() print('总共耗费了%f秒' % (end - start)) """ start = time.time() download('Python从入门到住院.pdf') download('Pekin Hot.avi') end = time.time() print('总共耗费了%f秒' % (end - start)) """ if __name__ == '__main__': main()比如以上代码,需要进行的两个操作,由于无关联,完全可以采取多进程的操作
3.通过面向对象的方式来写多进程或多线程
from threading import Thread from random import * import time class Download(Thread): def __init__(self, filename): super().__init__() self._filename = filename # 钩子函数(hook) / 回调函数(callback) def run(self): print('开始下载%s...' % self._filename) delay = randint(5, 15) time.sleep(delay) print('%s下载完成, 用时%d秒' % (self._filename, delay)) def main(): start = time.time() d1 = Download('东京热.rmvb') d2 = Download('加勒比.avi') d1.start() d2.start() d1.j f3d2 oin() d2.join() end = time.time() print('总共耗费了%f秒' % (end - start)) if __name__ == '__main__': main()在以上代码中,可以很容易发现,其实我们并没有调用Download类中的run函数,但是在结果中,run函数却被自动调用了,这是因为run()函数是一个钩子函数,也叫作回调函数,在类中的作用和魔法函数很像,但是run的调用前提是必须让进程或者线程开始
4.当多个线程同时访问一个资源的时候 就有肯能因为竞争资源导致资源的状态错误被多个线程访问的资源我们通常称之为临界资源对临界资源的访问需要加上保护
import time from threading import Thread, Lock class Account(object): def __init__(self): self._balance = 0 self._lock = Lock() @property def balance(self): return self._balance def deposit(self, money): # 当多个线程同时访问一个资源的时候 就有肯能因为竞争资源导致资源的状态错误 # 被多个线程访问的资源我们通常称之为临界资源 对临界资源的访问需要加上保护 if money > 0: self._lock.acquire() # 放锁 try: new_balance = self._balance + money time.sleep(0.01) self._balance = new_balance finally: self._lock.release() # 释放锁 class AddMoneyThread(Thread): def __init__(self, account, money): super().__init__() self._account = account self._money = money def run(self): self._account.deposit(self._money) def main(): account = Account() tlist = [] for i in range(100): t = AddMoneyThread(account, 1) tlist.append(t) t.start() for t in tlist: t.join() print('账户余额:%d元' % account.balance) if __name__ == '__main__': main()但是同过上面的代码,可以很容易看出一个问题,就是,当加上所之后,程序的运行效率大大下降,所以如果不是真的必须要加上锁,最好别用
二、socket,client,服务端与客户端的编写
1.最简单的启服务器的方法
from socket import socket def main(): server = socket() # 新建立一个套接字对象 server.bind('127.0.0.1', 6789) # 绑定ip地址(网络上的主机的身份标识)和端口(用来区分不同服务的ip地址的扩展) server.listen(512) # 监听 print('服务器已经启动!正在监听...') while True: client, addr = server.accept() # 接收客户端信息 print(addr, '连接成功')通过accept方法接收客户端的连接,而accept方法是一个阻塞式方法 如果没有客户端连上,那么accept方法会让代码阻塞 直到有客户端连接成功才返回accept方法返回一个元组,元组中的第一个值是代表客户端的对象元组中的第二个值又是一个元组, 其中有客户端的IP地址和客户端的端口运行上面的代码,打开cmd命令窗口, 输入telnet 127.0.0.1 6789 就可以检查是否连接上了服务器
三、练习
案例一、通过多线程的方法,使用json下载图片(小福利)
# URL - Uniform Resource Locator # https://api.tianapi.com/meinv/?key=ea6c4700539ba230113dcdc0a14b7432 import requests import json from threading import Thread import time class Filename(Thread): def __init__(self, p, i): super().__init__() self._p = p self._i = i def run(self): print('第%d张图片开始下载' % self._i) resp = requests.get(self._p) filename = self._p[self._p.rfind('/') + 1:] with open(filename, 'wb') as fs: fs.write(resp.content) # time.sleep(0.01) print('第%d张图片下载完成' % self._i) def main(): # request / response resp = requests.get('https://api.tianapi.com/meinv/?key=ea6c4700539ba230113dcdc0a14b7432&num=50') mydict = json.loads(resp.text) print(mydict) picture = [] for tempdict in mydict['newslist']: pic_url = tempdict['picUrl'] picture.append(pic_url) # start = time.time() for i in range(len(picture)): Filename(picture[i], i+1).start() if __name__ == '__main__': main()可以和容易看出来,使用了线程之后,速度真的快到飞起!
案例二、实现不同机器客户端与服务端的连接
服务端:import socket from threading import Thread def main(): class SocketsRecv(Thread): def __init__(self): super().__init__() def run(self): while True: text = clients.recv(512) print('客户端发来的消息:' + text.decode('utf-8')) class SocketSend(Thread): def __init__(self): super().__init__() def run(self): while True: str1 = input() clients.send(str1.encode('utf-8')) print('您向客户端发出了信息!') # 创建一个套接字 server = socket.socket() server.bind(('10.7.189.89', 6789)) # 监听 server.listen(512) print('服务器已启动!正在监听...') while True: clients, addr = server.accept() # 接收客户端信息 print(addr, '连接成功!') try: SocketSend().start() SocketsRecv().start() except ConnectionResetError: print('客户端断开连接!') if __name__ == '__main__': main()客户端:
from socket import socket from threading import Thread def main(): class ClientSend(Thread): def run(self): while True: data = client.recv(512) #print(type(data)) print('服务端的消息:' + data.decode('utf-8')) class ClientRecv(Thread): def run(self): while True: text = input() client.send(text.encode('utf-8')) print('您向服务端发出信息!') client = socket() client.connect(('10.7.189.103', 1202)) ClientSend().start() ClientRecv().start() if __name__ == '__main__': main()
相关文章推荐
- 【python学习笔记】3.输入与输出
- Python-学习笔记(一)——环境配置+IDE搭建(WingIDE)
- Python学习笔记 capture 1
- 廖雪峰Python学习笔记
- Python爬虫初学者学习笔记(带注释)
- Python学习笔记(三)
- Python学习笔记04----计算(a^n) % b并输出结果
- Python 学习笔记 - 2.自省
- Python 学习笔记 - 协程
- Python学习笔记(一)
- python学习笔记04(点球游戏)
- Python学习笔记
- python学习笔记之一:列表与元组
- “笨方法”学习Python笔记(2)-VS Code作为文本编辑器以及配置Python调试环境
- python基础学习笔记(一)
- 学习笔记:rabbitmq+python
- 【python学习笔记】7:用python实现爬虫-基础
- 【学习笔记】Python中的正则表达式re
- python进阶学习笔记(四)——python中访问限制、创建类属性、定义实例方法、定义类方法、类的继承
- 【学习总结】Python基础知识笔记2