大家好,今天是21天python打卡的第9天,上一篇讲了python的相关技能,比如将时间日期的处理,数据文件的读写,以及数据库的简单操作。今天来说说源码打包和网络编程。

活动地址:CSDN21天学习挑战赛
学习的最大理由是想摆脱平庸,早一天就多一份人生的精彩;迟一天就多一天平庸的困扰。
目录
1、有一个pypi官网账号;注册地址
2、更新pip版本到最新:py -m pip install --upgrade pip
3、通过pip安装twine:要使用twine来上传代码;
4、安装编译工具:pip install --upgrade build
第一步,创建本地目录结构;
- daletou/
- └── src/
- └── daletou/
- ├── __init__.py
- └── dlt.py
以上除了src和__init__.py为固定值,其他都可以自定义;目录结构需保持一致;
其中__init__.py是为了将目录作为包导入,默认可以为空。
dlt.py是包中的一个模块,主要是提供的功能供下载人调用
如在dlt.py中输入如下代码:
代码中提供的一个函数,返回指定的字符串;
此功能是最终上传的pypi后提供给外部的方法;
- from random import sample
-
- def random_dlt(num=1,reds_pre=None,blue_pre=None):
- result = []
- for n in range(num):
- if reds_pre is None:
- reds = sample([n for n in range(1,36)],5)
- if blue_pre is None:
- blues = sample([n for n in range(1,13)],2)
-
- reds.sort()
- blues.sort()
- result.append(' '.join(red_balls) + ' + '+ ' '.join(blue_balls))
- return '\n'.join(result)
第二步:创建上传所需的文件;
最终得文件结构如下:
- daletou/
- ├── LICENSE
- ├── pyproject.toml
- ├── README.md
- ├── setup.py
- ├── src/
- │ └── daletou/
- │ ├── __init__.py
- │ └── dlt.py
pyproject.toml告诉构建工具构建项目所需的内容。
打开pyproject.toml并输入以下内容:
- [build-system]
- requires = ["setuptools>=42"]
- build-backend = "setuptools.build_meta"
README.md 是包的描述信息,markdown格式书写;
- # study Package
- This is a simple study package.
setup.py是setuptools的构建脚本。它告诉 setuptools 您的包(例如名称和版本)以及要包含的代码文件。
打开setup.py并输入以下内容。更改name 以包含您的用户名;这可确保您拥有唯一的包名称,并且您的包不会与其他人按照本教程上传的包冲突。
-
- import setuptools
-
- with open("README.md", "r", encoding="utf-8") as fh:
- long_description = fh.read()
-
- setuptools.setup(
- name="daletou",
- version="0.0.1",
- author="Author",
- author_email="author@example.com",
- description="example package",
- long_description=long_description,
- long_description_content_type="text/markdown",
- #url="",
- #project_urls={},
- package_dir={"": "src"},
- packages=setuptools.find_packages(where="src"),
- python_requires=">=3.6",
- )
部分属性说明:
还有有个配置文件setup.cfg,相对于setup.py,此文件配置是静态元数据,内容基本不变;推荐使用setup.py配置;
具体可参考pypi官网解释;
LICENSE是许可文件,参考以下输入既可;
- Copyright (c) 2018 The Python Packaging Authority
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
在pyproject.toml文件同级目录;打开命令行工具;
执行命令:
python -m build
首先执行命令
twine check dist/*
检查是否存在问题,有问题提示,需要解决;
若无问题;执行以下命令上传;
twine upload dist/*
验证是否可以安装:
访问上传成功的地址,是否存在你上传的包;
使用pip install *** 验证是否可以安装;
import socket
创建服务端
-
- import socket
-
-
- def server():
- print('服务端启动')
-
- #创建Tcp/Ip套接字对象
- s=socket.socket(socket.AF_INET,socket.SOCK_STREAM) #流式Socket
- #创建Udp/Ip套接字对象
- #s=socket.socket(socket.AF_INET,socket.SOCK_DGRAM) #数据报式Socket
- s.bind(('127.0.0.1',18080)) # 绑定地址
- s.listen(3) # 建立最多3个链接
- while True:
- conn,addr= s.accept() # 等待客户端连接
- print('欢迎{}'.format(addr)) #打印访问的用户信息
- while True:
- data=conn.recv(1024)
- dt=data.decode('utf-8') #接收一个1024字节的数据
- print('服务端收到:',dt)
- aa=input('服务端发送:')
- if aa=='quit':
- conn.close() #关闭来自客户端的连接
- s.close() #关闭服务器端连接
- else:
- conn.send(aa.encode('utf-8')) #发送数据
-
创建客户端
- import socket
- def client():
- import sys
- print('客户端启动')
- c=socket.socket() # 创建socket对象
- c.connect(('127.0.0.1',18080))
- print(c.getpeername())#获取远程的地址 #跟服务端建立连接
- while True:
- ab=input('客户端发送:')
- if ab=='quit':
- c.close() #关闭客户端连接
- sys.exit(0)
- else:
- c.send(ab.encode('utf-8')) #发送数据
- data=c.recv(1024) #接收一个1024字节的数据
- print('客户端收到:',data.decode('utf-8')) #输出接收的信息
先启动服务端,在启动客户端,实现简单通信功能
5、以上只能实现单一通信,发送后必须等待接收,实现群聊的需要使用到多线程;
使用UDP通信
创建群聊服务端:
- #群聊服务端
- def serverMany():
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) # 创建socket对象
- addr = ('127.0.0.1', 9999)
- s.bind(addr) # 绑定地址和端口
- print('服务端启动,地址:',addr)
- user = {} # 存放字典{addr:name}
- while True:
- try:
- data, addr = s.recvfrom(1024) # 等待接收客户端消息存放在2个变量data和addr里
- if not addr in user: # 如果addr不在user字典里则执行以下代码
- for address in user: # 从user遍历数据出来address
- s.sendto(data + ' 进入聊天室...'.encode('utf-8'), address) # 发送user字典的data和address到客户端
- user[addr] = data.decode('utf-8') # 接收的消息解码成utf-8并存在字典user里,键名定义为addr
- continue # 如果addr在user字典里,跳过本次循环
-
- if 'EXIT'.lower() in data.decode('utf-8'):#如果EXIT在发送的data里
- name = user[addr] #user字典addr键对应的值赋值给变量name
- user.pop(addr) #删除user里的addr
- for address in user: #从user取出address
- s.sendto((name + ' 离开了聊天室...').encode(), address) #发送name和address到客户端
- else:
- print('"%s" from %s:%s' %(data.decode('utf-8'), addr[0], addr[1]))
- for address in user: #从user遍历出address
- if address != addr: #address不等于addr时间执行下面的代码
- s.sendto(data, address) #发送data和address到客户端
-
- except ConnectionResetError:
- print('服务端异常')
创建客户端;
-
- name = '用户昵称'
- def recv(sock, addr):
- '''
- 一个UDP连接在接收消息前必须要让系统知道所占端口
- 也就是需要send一次,否则win下会报错
- '''
- sock.sendto(name.encode('utf-8'), addr)
- while True:
- data = sock.recv(1024)
- print(data.decode('utf-8'))
-
-
- def send(sock, addr):
- '''
- 发送数据的方法
- 参数:
- sock:定义一个实例化socket对象
- server:传递的服务器IP和端口
- '''
- while True:
- string = input('正在输入:')
- message = name + ' : ' + string
- data = message.encode('utf-8')
- sock.sendto(data, addr)
- if string.lower() == 'EXIT'.lower():
- break
-
- def main():
- import threading
- global name
- name = input('请输入你的名称:')
- '''
- 主函数执行方法,通过多线程来实现多个客户端之间的通信
- '''
- s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
- server = ('127.0.0.1', 9999)
- tr = threading.Thread(target=recv, args=(s, server), daemon=True)
- ts = threading.Thread(target=send, args=(s, server))
- tr.start()
- ts.start()
- ts.join()
- s.close()
-
- main()
今天就介绍到这里,下一篇我们将要介绍网络爬虫相关概念。