【21天python打卡】第9天 基础技能(2)

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

源码打包

  • 为什么打包源码
    如果你想让你的实现的python代码,通过pip install 方式供所有人进行下载;那就需要将代码上传到PyPi上,这样才能让所有人使用;


如何打包源码上传:

  • 前提条件:

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格式书写;

1. # study Package
2. 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",
)

部分属性说明:


name是您的包的分发名称。这可以是任何名称;

version是包版本。

author并author_email用于标识包的作者。

description是一个简短的、一句话的包摘要。

long_description是包的详细说明。

long_description_content_type: 描述使用什么类型的标记。

url是项目主页的 URL。可不写。

project_urls 显示的任意数量的链接。通常是文档、问题跟踪器等。

package_dir是一个字典,src目录被指定为根包。

packages 包含在分发包中的所有 Python导入包的列表;

python_requires给出项目支持的 Python 版本。

还有有个配置文件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/*

检查是否存在问题,有问题提示,需要解决;

若无问题;执行以下命令上传;

twine upload dist/*


网络编程


1、网络编程基础:

Sockets(套接字)可以在一个进程内,在同一机器上的进程之间,或者在不同主机的进程之间进行通信,主机可以是任何一台有连接互联网的机器。

Socket主要是使用IP地址,协议,端口号来标识一个进程。端口号的范围为0~65535(用户端口号一般大于1024),协议有很多种,经常用到的就是TCP,IP,UDP等;


2、python中的内置库socket

  • python中的socket库提供了处理公共传输的特定类,以及一个用于处理其余部分的通用接口。
  • socket是内置库,无需安装;


3、导入方式:

import socket


4、使用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()
相关文章
|
1天前
|
人工智能 Python
【Python实用技能】建议收藏:自动化实现网页内容转PDF并保存的方法探索(含代码,亲测可用)
【Python实用技能】建议收藏:自动化实现网页内容转PDF并保存的方法探索(含代码,亲测可用)
14 0
|
2月前
|
数据采集 UED 开发者
深入浅出Python协程:提升你的异步编程技能
在当今快速发展的软件开发领域,异步编程已成为提高应用性能和用户体验的关键技术之一。本文将深入探讨Python中的协程(coroutine)机制,它作为异步编程的核心,可以帮助开发者有效管理IO密集型任务,从而提升程序的执行效率。通过本文,你不仅能够理解协程的基本概念和工作原理,还将学习到如何在实际项目中灵活运用协程来解决复杂的编程问题。
|
4月前
|
机器学习/深度学习 自然语言处理 算法
机器学习基础:Python数据分析的必备技能
机器学习基础:Python数据分析的必备技能
60 2
|
7月前
|
数据可视化 数据挖掘 Python
Python3,一次掌握这些数据可视化图表技能,老板不给涨薪都不好意思。
Python3,一次掌握这些数据可视化图表技能,老板不给涨薪都不好意思。
44 0
|
9月前
|
机器学习/深度学习 人工智能 算法
Python编程入门基础及高级技能、Web开发、数据分析和机器学习与人工智能
Python编程入门基础及高级技能、Web开发、数据分析和机器学习与人工智能
133 0
|
9月前
|
数据采集 Dart 前端开发
【前端】从JavaScript到Python:我的技能扩展之路
【前端】从JavaScript到Python:我的技能扩展之路,简单介绍一下自己吧\~我是一名应届生,专业是铁路方面的,自己从小就喜欢捣鼓计算机这些,导致自己一步步的走上了“不归路”。
【前端】从JavaScript到Python:我的技能扩展之路
|
10月前
|
存储 索引 Python
把你的 Python 技能从 “Hello World“ 升级到 “万能钥匙“:掌握 Python 的输出、输入、数据类型转换和运算符!
把你的 Python 技能从 “Hello World“ 升级到 “万能钥匙“:掌握 Python 的输出、输入、数据类型转换和运算符!
把你的 Python 技能从 “Hello World“ 升级到 “万能钥匙“:掌握 Python 的输出、输入、数据类型转换和运算符!
|
10月前
|
Python
Python应用 | 读写docx文件 (值得收藏的技能)
Python应用 | 读写docx文件 (值得收藏的技能)
102 0
|
10月前
|
NoSQL 关系型数据库 MySQL
【21天python打卡】第8天 基础技能(1)
​大家好,今天是21天python打卡的第8天,上一篇讲了如何创建python如何创建类,抽象类,访问限制的说明。今天说说python的相关技能,比如将时间日期的处理,数据文件的读写,以及数据库的简单操作。
46 0
|
11月前
|
数据库连接 Python
提升Python函数技能
提升Python函数技能

热门文章

最新文章