diff --git a/test32.py b/test32.py new file mode 100644 index 0000000..4792c79 --- /dev/null +++ b/test32.py @@ -0,0 +1,79 @@ +#!/ussr/bin/env python 3 +# -*- coding: utf-8 -*- + +'练习多进程与进程间通信' + +__author__ = 'sergiojune' +from multiprocessing import Process, Pool, Queue +import os +import time +from random import random + + + +# print('parent process(%s) is running' % os.getpid()) +# 定义子进程需要运行的函数 +# def run(name): +# print('I am runing,I is process(%s)' % os.getpid()) +# 在使用这个进程时,需要使用if __name__ == '__main__这个语句来开父进程,要不会出错 +# if __name__ == '__main__': +# # 创建子进程 +# p = Process(target=run, args=('test',)) +# # 开启进程 +# p.start() +# # 让子进程运行完再运行下面的父进程 +# p.join() +# print('End...........') + + + +# 使用进程池批量开启进程 +# def run(name): +# print('task %s is running, process %s' % (name, os.getpid())) +# start = time.time() +# time.sleep(random()*3) +# end = time.time() +# print('%s is run %0.2f seconds process %s' % (name, (end - start), os.getpid())) +# +# +# if __name__ == '__main__': # 开启多进程这个语句是必须的 +# print('parent process %s is running' % os.getpid()) +# # 创建进程池 +# p = Pool(4) +# for x in range(5): +# p.apply_async(run, args=(x,)) +# # 关闭进程池,不能再添加进程 +# p.close() +# # 要实现这个方法之前必须关闭进程池 +# p.join() +# print('parent process %s end' % os.getpid()) + + + +# 实现进程间通信 +def write(q): + print('process %s is writing' % os.getpid()) + for x in 'ABC': + q.put(x) + print(' %s write %s' % (os.getpid(), x)) + + +def read(q): + print('process %s is read' % os.getpid()) + while True: + value = q.get(True) + print('info is %s' % value) + + +if __name__ == '__main__': + q = Queue() + print('parent is running') + pw = Process(target=write, args=(q,)) + pr = Process(target=read, args=(q,)) + # 开启进程 + pw.start() + pr.start() + pw.join() + # 由于read方法不能自行停止,所以需要强制tingz + pr.terminate() + print('end------') diff --git a/test33.py b/test33.py new file mode 100644 index 0000000..8837229 --- /dev/null +++ b/test33.py @@ -0,0 +1,65 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'练习多线程' + +__author__ = 'sergiojune' +import threading +import multiprocessing + + +def run(): + print('thread %s is running' % threading.current_thread().name) + for x in range(5): + print('thread %s ==> %d' % (threading.current_thread().name, x)) + print('thread %s end' % threading.current_thread().name) + + +print('thraed %s is running' % threading.current_thread().name) +t = threading.Thread(target=run, name='loopthread') +# 开启线程 +t.start() +t.join() +print('thread %s is end' % threading.current_thread().name) + + +# 多线程的锁 +balance = 0 +def change(n): + global balance + balance = balance + n + balance = balance - n + print(balance) + + +def run_thread(): + l = threading.Lock() + for x in range(1, 100000): + try: + # 获取锁 + l.acquire() + change(x) + finally: + # 释放锁 + l.release() + + +t1 = threading.Thread(target=run_thread) +t2 = threading.Thread(target=run_thread()) +t1.start() +t2.start() +t1.join() +t2.join() +print('end') + + +def loop(): + x = 0 + while True: + x = x ^ 1 + + +for x in range(multiprocessing.cpu_count()): # 根据cpu的数量来开线程 + t = threading.Thread(target=loop) + t.start() + diff --git a/test35.py b/test35.py new file mode 100644 index 0000000..c208150 --- /dev/null +++ b/test35.py @@ -0,0 +1,66 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'练习分布式进程 ' + +__author__ = 'sergiojune' +import queue, random +from multiprocessing.managers import BaseManager +# 此文件用来发送和接受结果,test36.py用于处理结果 + +# 创建通信工具 +# 发送任务 +post_task = queue.Queue() +# 接受结果 +result_task = queue.Queue() + + +class QueueManager(BaseManager): + pass + + +# 定义的函数解决下面的坑 +def posttq(): + return post_task + + +def resulttq(): + return result_task + + +def start(): + # 注册任务 + # 这里有个坑,在window系统下callable不能为匿名函数,原因是不能被序列化,所以在这里我们需要定义函数 + QueueManager.register('post_task_queue', callable=posttq) # 第一个参数为注册名字 + QueueManager.register('result_task_queue', callable=resulttq) + + # 绑定窗口,设置验证码 + manager = QueueManager(address=('127.0.0.1', 500), authkey=b'abc') # 第一个参数为地址和端口,第二个参数为验证码,防止别人骚扰 + + # 启动管理 + manager.start() + # 通过管理器获取通信 + post = manager.post_task_queue() + result = manager.result_task_queue() + + # 进行发送数据 + print('try post data') + for x in range(10): + n = random.randint(1, 1000000) + print('put %d' % n) + post.put(n) + + # 接受结果 + print('try get result') + for x in range(10): + # timeout表示超时获取数的最长时间 + value = result.get(timeout=10) + print('get result', value) + + # 关闭管理器 + manager.shutdown() + print('master end') + + +if __name__ == '__main__': + start() diff --git a/test36.py b/test36.py new file mode 100644 index 0000000..843fabc --- /dev/null +++ b/test36.py @@ -0,0 +1,39 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'处理分布式进程发送的数据' + +__author__ = 'sergiojune' +from multiprocessing.managers import BaseManager +import time, queue + + +class QueueManager(BaseManager): + pass + + +# 注册到网络上 +QueueManager.register('post_task_queue') # 由于只是从网络上获取queue,所以不需要写callable方法 +QueueManager.register('result_task_queue') +# 连接到网络 +address = '127.0.0.1' # 这个是网络地址 +manager = QueueManager(address=(address, 500), authkey=b'abc') # 这些必须与发送的一致,要不会连不上 +# 连接 +manager.connect() +# 获取queue +post = manager.post_task_queue() +result = manager.result_task_queue() + +# 处理数据 +print('tyr get value') +for x in range(10): + try: + v = post.get(timeout=10) + print('get value %d' % v) + r = v*v + print('put value %d to result' % r) + time.sleep(1) + result.put(r) + except queue.Empty as e: + print('Queue is empty') +print('work exit') diff --git a/test37.py b/test37.py new file mode 100644 index 0000000..4940645 --- /dev/null +++ b/test37.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'练习正则表达式' + +__author__ = 'sergiojune' +import re + + +# 作业:尝试写一个验证Email地址的正则表达式。版本一应该可以验证出类似的Email +a = 'someone@gmail.com' +b = 'bill.gates@microsoft.com' +# 匹配邮箱的正则表达式,返回一个正则对象 +re_mail = re.compile('[\.\w]*@[\w]+.[\w]+') +m = re_mail.match(a) +print(m.group()) +g = re_mail.match(b) +print(g.group()) + + +# 版本二: +a = ' tom@voyager.org => Tom Paris' +b = 'bob@example.com => bob' +mail = re.compile('([\w]+|[<>\w\s]+)@[\w]+.[\w]+') +aa = mail.match(a) +bb = mail.match(b) +print(aa.group()) +print(bb.group()) diff --git a/test38.py b/test38.py new file mode 100644 index 0000000..61ce759 --- /dev/null +++ b/test38.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'练习内建模块致datetime' + +__author__ = 'sergiojune' +from datetime import datetime, timedelta, timezone +import re + +# 获取现在时间 +dt = datetime.now() +print(dt) +print(type(dt)) + +# 获取指定某日的时间,即是创建实例 +ddt = datetime(2017, 10, 15, 12, 35, 56) +print(ddt) # 类型为datetime.datetime + +# 将datetime转为timestamp +ts = dt.timestamp() +print(ts) +print(type(ts)) # 类型为float +# 将timestamp转为datetime +d = datetime.fromtimestamp(ts) +print(d) +# 将timestamp转为标准的utc时间,比北京时间少了八小时 +d = datetime.utcfromtimestamp(ts) +print(d) + +# 将字符串转为时间 +s = '2017:12:12 11:11:11' +sd = datetime.strptime(s, '%Y:%m:%d %H:%M:%S') # 第二个参数为字符串的时间格式 +print(sd) +print(type(sd)) + +# 将时间转为字符串,参数为转为字符串的格式 +ds = sd.strftime('%Y:%m:%d %H:%M:%S') +print(ds) +print(type(ds)) + + +# 将时间进行加减 +print('之前:', dt) +dt = dt + timedelta(hours=5,minutes=25) +print(dt) +dt = dt + timedelta(days=5) +print(dt) + +print('-------------------') +# 将本地datetime设一个时区 +tz_local = timezone(timedelta(hours=8)) +d = datetime.now() +print(d) +# 强行设置时区,tzinfo就是时区信息 +now = d.replace(tzinfo=tz_local) +print(now) + +print('----------------------') +# 时区时间任意转换 +# 拿到utc时间,并设置时区 +d = datetime.utcnow().replace(tzinfo=timezone.utc) +print(d) +# 转为北京时间的时区 +bj_utc = d.astimezone(tz=timezone(timedelta(hours=8))) +print(bj_utc) +# 转为东京时间 +dj_utc = d.astimezone(tz=timezone(timedelta(hours=9))) +print(dj_utc) +# 也可以直接利用北京时间转为东京时间 +dj_utc = bj_utc.astimezone(tz=timezone(timedelta(hours=9))) +print(dj_utc) +# 所以用astimezone()这个方法可以任意转换时区 + + +# 作业:假设你获取了用户输入的日期和时间如2015-1-21 9:01:30,以及一个时区信息如UTC+5:00,均是str,请编写一个函数将其转换为timestamp +def to_timestamp(time, tz): + # 将字符串转为时间 + time = datetime.strptime(time, '%Y-%m-%d %H:%M:%S') + # 设置该时间的时区 + time = time.replace(tzinfo=timezone(timedelta(hours=tz))) + time = time.timestamp() + return time + + +print('---------------') +time1 = '2015-6-1 08:10:30' +utc1 = 'UTC+7:00' +# 用正则匹配出时间 +utc1 = int(re.search('UTC([+-][\d]{1,2}):[\d]{2}', utc1).group(1)) +print(utc1) +time = to_timestamp(time1, utc1) +print(time) + +time2 = '2015-5-31 16:10:30' +utc2 = 'UTC-09:00' +# 用正则匹配出时间 +utc2 = int(re.search('UTC([+-][\d]{1,2}):[\d]{2}', utc2).group(1)) +print(utc2) +time2 = to_timestamp(time2, utc2) +print(time2) diff --git a/test39.py b/test39.py new file mode 100644 index 0000000..1455bf0 --- /dev/null +++ b/test39.py @@ -0,0 +1,80 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'练习内建模块之collections' + +__author__ = 'sergiojune' +from collections import namedtuple, defaultdict, deque, OrderedDict, Counter + +# 弄一个可以根据名字来取数的元组 +at = namedtuple('Point', ['x', 'y']) # 第一个参数为描述事物类型, 第二个参数为元组的位置名字 +p = at(1, 2) # 新建一个元组 +# 根据名字来取元素 +print(p.x) # 这就可以看作是一个坐标点 +print(p.y) + +# 有默认值的dict +dd = defaultdict(lambda:'not') # 参数为遇到不存在键时的处理的方法 +dd['age'] = 20 +print(dd['age']) # 存在 +print(dd['a']) # 不存在 + + +# 使用队列,比list的插入数据和删除数据快,支持从头或者尾删除或插入 +d = deque([1, 2, 3, 6]) +print(d) +# 从头插入数据 +d.appendleft(5) +print(d) +# 删除头部数据 +d.popleft() +print(d) + +# 让字典保持有序 +od = OrderedDict([('x', 3), ('y', 6), ('z', 6)]) +print(od) +# 还可以添加,与dict用法一样 +ood = OrderedDict() +ood['f'] = 5 +ood['s'] = 9 +ood['e'] = 7 +print(ood) + + +# 用计数器,直接算出某一个字符串里面字符出现的个数 +s = 'mynameissergiojune' +c = Counter(s) +print(c) + + +# 利用OrderedDict实现一个先进先出的字典,超过最大容量的时候就删除 +class LastUpdateDict(OrderedDict): + def __init__(self, max): + super(LastUpdateDict, self).__init__() + self.max = max + + def __setitem__(self, key, value): + # 看看有没有重复键 + contains = 1 if key in self.keys() else 0 + # 判断最大长度 + if len(self) - contains >= self.max: + last = self.popitem(last=False) # last 为false时就删除第一个添加的键值对,否则删除最后的键值对 + print('pop', last) + # 增加元素 + if contains: # 键原来存在,直接修改 + del self[key] + print('update', key, value) + else: + print('add', key, value) + OrderedDict.__setitem__(self, key, value) + + +lud = LastUpdateDict(3) +lud['a'] = 1 +lud['b'] = 2 +lud['c'] = 3 +print(lud) +lud['d'] = 4 +print(lud) +lud['b'] = 5 +print(lud) diff --git a/test40.py b/test40.py new file mode 100644 index 0000000..1b03856 --- /dev/null +++ b/test40.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'练习内建模块之base64' + +__author__ = 'sergiojune' +import base64 + +# 进行base64编码,转为字符串 +b = b'binary\x00strg=' +bs = base64.b64encode(b) +print(bs) +# 解码 +b = base64.b64decode(bs) +print(b) + + +# 对于网页的安全编码 +s = b'i\xb7\x1d\xfb\xef\xff' +bs = base64.b64encode(s) +print(bs) +bs = base64.urlsafe_b64encode(s) +print(bs) + + +# 作业:请写一个能处理去掉=的base64解码函数 +def safe_base64_decode(s): + while len(s) % 4 !=0: + s += b'=' + bs = base64.b64decode(s) + return bs + + +# 测试: +assert b'abcd' == safe_base64_decode(b'YWJjZA=='), safe_base64_decode('YWJjZA==') +assert b'abcd' == safe_base64_decode(b'YWJjZA'), safe_base64_decode('YWJjZA') +print('ok') \ No newline at end of file diff --git a/test41.py b/test41.py new file mode 100644 index 0000000..a32a30a --- /dev/null +++ b/test41.py @@ -0,0 +1,45 @@ +#!/usr/bin/env python3 +# -*- conding: utf-8 -*- + +'练习内建模块之struct' + +__author__ = 'sergiojune' +import struct,base64 + +# 这个模块是将bytes与其他二进制数据互相转换 +# 将任意数据类型转为bytes +i = 10249999 +b = struct.pack('>I', i) # 第一个参数为处理指令 +print(b) + +s = 123.456 +b = struct.pack('f', s) +print(b) + + +# 将bytes转为其他任意类型 +s = struct.unpack('f', b) +print(s) + +s = b'\x42\x4d\x38\x8c\x0a\x00\x00\x00\x00\x00\x36\x00\x00\x00\x28\x00\x00\x00\x80\x02\x00\x00\x68\x01\x00\x00\x01\x00\x18\x00' +un = struct.unpack('' % self.name, end='') + + def put_end(self): + print('' % self.name) + + +@contextlib.contextmanager +def create(name): + h = Html(name) + h.put_start() + yield h + h.put_end() + + +with create('h1') as h: + print('我是标题', end='') + + +# 如果一个对象没有实现上下文方法,我们还可以用colsing这个方法 +with contextlib.closing(requests.get('https://www.liaoxuefeng.com/wiki/0014316089557264a6b348958f449949df42a6d3a2e542c000/001478651770626de401ff1c0d94f379774cabd842222ff000')) as f: + print(f.text) + + + diff --git a/test46.py b/test46.py new file mode 100644 index 0000000..3ef2473 --- /dev/null +++ b/test46.py @@ -0,0 +1,84 @@ +#!/usr/bin/env python3 +# -*- conding: utf-8 -*- + +'练习内建模块之HTMLParser' + +__author__ = 'sergiojune' +from html.parser import HTMLParser +import requests + + +class MyHTMLParser(HTMLParser): + + def handle_starttag(self, tag, attrs): # 这个是处理开始标签 + print('<%s>' % tag, list(attrs)) + + def handle_endtag(self, tag): # 这个是处理结束标签 + print('' % tag) + + def handle_data(self, data): # 这个是处理标签里的内容 + print(data) + + def handle_comment(self, data): # 这个是处理注释 + print('') + + def handle_entityref(self, name): # 这个是处理特殊字符,比如  + print('&%s;' % name) + + def handle_charref(self, name): # 这个是处理特殊字符,比如Ӓ + print('&#%s;' % name) + + +parser = MyHTMLParser() +parser.feed(''' + + + +

Some html HTML tutorial...
END

+''') + + +# 作业:找一个网页,例如https://www.python.org/events/python-events/,用浏览器查看源码并复制,然后尝试解析一下HTML,输出Python官网发布的会议时间、名称和地点。 +class DealHTML(HTMLParser): + def __init__(self): + super(DealHTML, self).__init__() + self.thing = 0 + self.time = 0 + self.address = 0 + + def handle_starttag(self, tag, attrs): + if len(attrs) == 1: + if 'python-events' in list(attrs)[0][1]: # 获取工作事件 + print('' % list(attrs)[0][1], end='') + self.thing = 1 + if 'datetime' in list(attrs)[0][0]: # 获取工作时间 + print('<%s>' % list(attrs)[0][0], end='') + self.time = 1 + if 'location' in list(attrs)[0][1]: # 获取工作地点 + print('<%s>' % list(attrs)[0][1], end='') + self.address = 1 + + def handle_data(self, data): + if self.thing: + print(data, end='') + if self.time: + print(data, end='') + if self.address: + print(data, end='') + + def handle_endtag(self, tag): + if self.thing: + print('' % tag) + self.thing = 0 + if self.time: + print('' % tag) + self.time = 0 + if self.address: + print('' % tag) + print('') + self.address = 0 + + +response = requests.get('https://www.python.org/events/python-events/').text +dh = DealHTML() +dh.feed(response) diff --git a/test47.py b/test47.py new file mode 100644 index 0000000..360161a --- /dev/null +++ b/test47.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 +# -*- conding: utf-8 -*- + +'练习第三方模块之pillow' + +__author__ = 'sergiojune' +from PIL import Image, ImageFilter, ImageDraw, ImageFont +import random +# 对图像进行缩小 +im = Image.open('test.jpg') +w, h = im.size # 获取图片的宽高 +print('origin image width is %d, height is %d' % (w, h)) +# 进行缩小一倍 +im.thumbnail((w//2, h//2)) # 参数是一个元组,对应的是宽高 +im.save('suoxiao.png', 'png') +print('now width is %d, height is %d' % (im.size[0], im.size[1])) + +# 还可以对图像进行模糊化 +im2 = im.filter(ImageFilter.BLUR) +im2.save('muhu.png', 'png') + + +# 利用这个模块产生验证码 +def rndchar(): # 产生随机字符 + return chr(random.randint(65, 90)) + + +def rndcolor(): # 随机颜色 + return (random.randint(64, 255), random.randint(64, 255), random.randint(64, 255)) + + +def rndcolor2(): + return (random.randint(32, 127), random.randint(32, 127), random.randint(32, 127)) + + +width = 240 +height = 40 +# 创建图像对象 +im = Image.new('RGB', (width, height), (255, 255, 255)) +# 创建字体 +font = ImageFont.truetype(r'E:\python_project\Lib\site-packages\matplotlib\mpl-data\fonts\ttf\cmsy10.ttf', 36) +# 创建画笔 +draw = ImageDraw.Draw(im) +# 填充图片 +for x in range(width): + for y in range(height): + draw.point((x, y), fill=rndcolor2()) +# 写文字 +for x in range(4): + draw.text((60*x+10, 10), rndchar(), font=font, fill=rndcolor()) + +# mohu +im.filter(ImageFilter.BLUR) +# 保存图片 +im.save('yan.png', 'png') diff --git a/test48.py b/test48.py new file mode 100644 index 0000000..64ee6ab --- /dev/null +++ b/test48.py @@ -0,0 +1,26 @@ +#!/usr/bin/env python3 +# -*- conding: utf-8 -*- + +'练习第三方模块之chardet' + +__author__ = 'sergiojune' +import chardet # 这个库是用来猜测字节码的编码方式的 + +s = b'hello world' +c = chardet.detect(s) +print(c) +# 结果:{'encoding': 'ascii', 'confidence': 1.0, 'language': ''},可以看出是ascii编码,第二个为概率,1.0表示百分百 + +s = '中国中文我爱你' +c = chardet.detect(s.encode('gbk')) +print(c) + +c = chardet.detect(s.encode('utf-8')) +print(c) + +# 看看日语的 +s = '最新の主要ニュース' +c = chardet.detect(s.encode('euc-jp')) +print(c) + +# encode()为编码,将字符串变为字节码,decode()为解码,将字节码转为字符串 diff --git a/test49.py b/test49.py new file mode 100644 index 0000000..ec6e3a6 --- /dev/null +++ b/test49.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'用于练习网络编程TCP' + +__author__ = 'sergiojune' +import socket, threading, time + +# 创建socket +# s = socket.socket(socket.AF_INET , socket.SOCK_STREAM) # 第一个参数为指定ipv4模式, 第二个参数指定为tup模式的面向流 +# # 建立连接 +# s.connect(('www.sina.com.cn', 80)) +# # 发送请求 +# s.send(b'GET / HTTP/1.1\r\nHost: www.sina.com.cn\r\nConnection: close\r\n\r\n') # 发送get请求,http协议 +# # 处理返回来的数据 +# buffer = [] +# while True: +# # 指定最大接受1024个字节 +# d = s.recv(1024) +# if d: +# buffer.append(d) +# else: +# break +# data = b''.join(buffer) +# # 关闭连接 +# s.close() +# 取出请求头和内容 +# header, body =data.split(b'\r\n') +# print(header) +# print(body) + + +# 建立服务器端 +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +# 绑定端口和地址,当有信息从这个端口发送过来时就捕捉 +s.bind(('127.0.0.1', 9999)) # 这个为本机ip,这个服务器只能接受本地的 +# 监听窗口 +s.listen(5) # 传入参数为最大的等待连接数 +print('await for connect') +def tcplink(sock, add): + print('here is a connector from %s:%s' % add) + # 向客户端发送数据 + sock.send(b'Welcome') + # 处理客户端发送来的数据 + while True: + d = sock.recv(1024) + time.sleep(1) + if not d or d == b'exit': + break + sock.send(('hello %s !' % d.decode('utf-8')).encode('utf-8')) + # 关闭连接 + sock.close() + print('connect is closed') + +# 用永久循环来等待客户端连接 +while True: + # 这个函数会返回一个客户端连接 + sock, add = s.accept() + # 创建线程来处理客户端的数据 + t = threading.Thread(target=tcplink, args=(sock, add)) + # 开启线程 + t.start() diff --git a/test50.py b/test50.py new file mode 100644 index 0000000..721bcf3 --- /dev/null +++ b/test50.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'配合test49文件的服务器,这文件当作客户端' + +__author__ = 'sergiojune' +import socket + +# 建立socket +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +# 连接地址 +s.connect(('127.0.0.1', 9999)) +# 接受返回的数据 +print(s.recv(1024).decode('utf-8')) +# 发送数据 +for x in [b'bob', b'amy', b'june']: + print('send %s' % x) + s.send(x) + print(s.recv(1024).decode('utf-8')) +# 发送退出数据 +s.send(b'exit') +s.close() +print('connect is closed from kehuuduan') diff --git a/test51.py b/test51.py new file mode 100644 index 0000000..81a0fac --- /dev/null +++ b/test51.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'练习UDP网络协议' + +__author__ = 'sergiojune' +import socket + +# 此文件用于当服务器 +# 创建socket +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 第二个参数为指定udp协议 +# 绑定端口,不需要监听 +s.bind(('127.0.0.1', 9999)) +print('await connect') +while True: + data, addr = s.recvfrom(1024) # 这个直接返回客户端的ip和请求信息 + print('connect form %s:%s' % addr) + # 发送数据回客户端 + s.sendto(b'hello %s' % data, addr) # 第二个参数为发送到的ip diff --git a/test52.py b/test52.py new file mode 100644 index 0000000..54ea8f1 --- /dev/null +++ b/test52.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +'udp配合test51文件的服务器,这文件当作客户端' + +__author__ = 'sergiojune' +import socket + +# 创建socket +s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) +# UDP协议不需要建立连接 +for x in [b'bret', b'tom', b'sergiojune']: + s.sendto(x, ('127.0.0.1', 9999)) + print(s.recv(1024).decode('utf-8')) +s.close() diff --git a/test53.py b/test53.py new file mode 100644 index 0000000..d7f37b8 --- /dev/null +++ b/test53.py @@ -0,0 +1,37 @@ +#!/usr.bin.env python 3 +# -*- coding: utf-8 -*- + +''' +练习python的协程0 +next(方法和next()方法在一定意义上是相同用法的,只不过next不能传递特定的值而next可以传递特定的值 +next() 和send(None) 方法是等价的,都是用于启动生成器返回值 +''' + +__author__ = 'sergiojune' + + +# 消费者 +def consumer(): + r = '' + while True: + n = yield r # 接受调用者发送的数据 + if not n: + return + print('consumer consume is %s' % n) + r = '200 OK' + + +def producer(c): # 这个函数先被执行 + c.send(None) # 这个语句必须写,而且参数固定,作用是启动上面的生成器 + x = 0 + while x < 5: + x = x+1 + print('producer is produce %d' % x) + r = c.send(x) # 发送数据,生成器接受数据,赋值给n变量 + print('consumer is return %s' % r) + # 关闭 + c.close() + + +c = consumer() +producer(c) diff --git a/test54.py b/test54.py new file mode 100644 index 0000000..5b29d01 --- /dev/null +++ b/test54.py @@ -0,0 +1,56 @@ +#!/usr.bin.env python 3 +# -*- coding: utf-8 -*- + +''' +练习python的asyncio +yield form 语句返回的值是后面表达式迭代后遇到StopIteration后再return(这个语句) 的值,无这个语句是返回None +''' + +__author__ = 'sergiojune' +import asyncio,threading + + +@asyncio.coroutine # 这个装饰器是把生成器标记成为coroutine +def hello(): + r = '' + print('hello world(%s)' % threading.current_thread()) + n = yield from asyncio.sleep(1) # 这个方法也是个coroutine,执行到这里后会等待该方法返回数给这个coroutine + print('hello again(%s)' % threading.current_thread()) + + +# 这是练习一个协程的 +# # 获取事件循环,就是eventloop +# loop = asyncio.get_event_loop() +# # 执行coroutine,参数是需要运行的协程 +# loop.run_until_complete(hello()) +# # 关闭 +# loop.close() + + +# 这个执行两个hello +# l = asyncio.get_event_loop() +# # 把协程放到eventloop里面 +# # 这两个方法是并发执行的 +# l.run_until_complete(asyncio.wait([hello(), hello()])) # wait()是将参数里的协程转为一个包括他们在内的单独协程 +# l.close() + + +# 练习用异步连接新浪搜狐和网易云 +def wget(host): + print('ready ro connect %s' % host) + connect = asyncio.open_connection(host, 80) + reader, writer = yield from connect # 这个io操作比较耗时,所以会执行下个协程 + header = 'GET/HTTP/1.1\r\nHost:%s\r\n\r\n' % host + writer.write(header.encode('utf-8')) + yield from writer.drain() # 用于刷新缓存区的内容,确保将内容提交上去 + while True: + line = yield from reader.readline() # 这个io操作有时不耗时,会直接运行整个循环 + if line == b'\r\n': + break + print('%s header>%s' % (host, line.decode('utf-8').strip())) + writer.close() + + +loop = asyncio.get_event_loop() +loop.run_until_complete(asyncio.wait([wget(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']])) +loop.close() diff --git a/test55.py b/test55.py new file mode 100644 index 0000000..af91a14 --- /dev/null +++ b/test55.py @@ -0,0 +1,52 @@ +#!/usr.bin.env python 3 +# -*- coding: utf-8 -*- + +''' +练习python的async/await +async:相当于asyncio.coroutine,可以用这个替换这个更加方便 +await:相当于yield form,把这个改成await即可替代 +以上都是在python3.5版本以上才有的 +''' + +__author__ = 'sergiojune' +import asyncio + + +async def hello(): # 这样就是相当于一个coroutine了 + print('hello world') + await asyncio.sleep(1) + print('hello again') + + +# loop = asyncio.get_event_loop() +# loop.run_until_complete(hello()) +# loop.close() + + +# 两个协程 +# loop = asyncio.get_event_loop() +# loop.run_until_complete(asyncio.wait([hello(), hello()])) +# loop.close() + + +# 再用这个方法连接搜狐新浪和网易 +async def wegt(host): + print('wegt %s ' % host) + # 连接 + connect = asyncio.open_connection(host, 80) + reader, writer = await connect + header = 'GET/HTTP/1.0\r\nHost:%s\r\n\r\n' % host + writer.write(header.encode('utf-8')) + await writer.drain() # 相当于刷新缓存 + while True: + line = await reader.readline() + if line == b'\r\n': + print() + break + print('%s header > %s' % (host, line.decode('utf-8').strip())) + connect.close() + + +loop = asyncio.get_event_loop() +loop.run_until_complete(asyncio.wait([wegt(host) for host in ['www.sina.com.cn', 'www.sohu.com', 'www.163.com']])) +loop.close() diff --git a/test56.py b/test56.py new file mode 100644 index 0000000..f414767 --- /dev/null +++ b/test56.py @@ -0,0 +1,38 @@ +#!/usr.bin.env python 3 +# -*- coding: utf-8 -*- + +''' +练习python的aiohttp +练习服务器上的异步操作 +''' + +__author__ = 'sergiojune' +import asyncio +from aiohttp import web + + +async def index(request): # 首页返回一个h1标签 + await asyncio.sleep(0.5) + return web.Response(body=b'

index

', content_type='text/html') + + +async def hello(request): # 根据url参数返回信息 + await asyncio.sleep(0.5) + return web.Response(body=b'

hello %s

' % request.match_info['name'], content_type='text/html') + + +# 初始化服务器,也是一个coroutine +async def init(loop): # 接受协程池 + app = web.Application(loop=loop) + # 添加反应路径 + app.router.add_route('GET', '/', index) + app.router.add_route('GET', '/hello/{name}', hello) + s = loop.create_server(app.make_handler(), '', 80) # 用loop.create_server创建tcp协议 + print('sever is start in 127.0.0.1:80') + return s + + +loop = asyncio.get_event_loop() +loop.run_until_complete(init(loop)) +loop.run_forever() # 服务器永远运行 +