Bootstrap

python之开发笔记

1、图标插件pyecharts

pyecharts - A Python Echarts Plotting Library built with love.

Document

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

#导包
from pyecharts.charts import Line
from pyecharts.options import TitleOpts,LegendOpts,ToolboxOpts,VisualMapOpts
#得到折线图对象
line = Line()
#添加x轴数据
line.add_xaxis(["中国","美国","英国"])
#添加y轴
line.add_yaxis("GDP",[30,20,10])

#设置全局配置
line.set_global_opts(
    title_opts=TitleOpts(title="标题",pos_left="center",pos_bottom="1%"),
    legend_opts = LegendOpts(is_show=True),
    toolbox_opts=ToolboxOpts(is_show=True),
    visualmap_opts=VisualMapOpts(is_show=True)
)


#生成图表
line.render()


执行上面代码,会上传对应的html图标页面

2、mysql连接插件pymysql

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

from pymysql import Connection

conn = Connection(
    host="localhost",
    port=3306,
    # autocommit=True, # 自动提交
    user="root",
    password="root",
    database="test",
    charset="utf8"
)

print(conn.get_server_info())
# 获取游标对象
cursor = conn.cursor()
# 选择数据库  与上面的   database="test",  二选1
#conn.select_db("test")  
# 执行sql
# cursor.execute("create table test_pumysql(id int);")

# 查询
cursor.execute("select * from user")
results = cursor.fetchall()
print(results)
for r in results:
    print(r)

cursor.execute("insert into user values( 31,'test', '123',234234)")
# 提交
conn.commit()
# 关闭连接
conn.close()

防止sql注入,构造参数列表,不直接sql字符串拼接

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

params = ""
cursor.execute("select * from user where name=%s",params)

3、数据分析插件pyspark

其中部分功能需要配合hadoop使用

下载hadoop安装包 tar.gz

解压到任意位置

在python代码中使用os模块配置:os.environ['HADOOP_HOME']=''

下载winutils.exe,并放到hadoop解压文件夹的bin目录内

下载hadoop.dll,并放到system32文件夹内

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import os

from pyspark import SparkConf,SparkContext

os.environ['PYSPARK_PYTHON'] = 'C:\Users\ASUS\PycharmProjects\pythonProject\venv\Scripts\python.exe'
os.environ['HADOOP_HOME']=''
conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
sc = SparkContext(conf=conf)

# 读取文件转换为rdd
file_rdd =sc.textFile("D:/aaa.txt")


rdd1.Map();
 #解嵌套 例如:[[],[],[]] => []
rdd1.flatMap();
#按key分组,进行聚合操作
rdd1.reduceByKey()
#对数据进行过滤
rdd1.filter(lambda num: num % 2 == 0)
print(rdd1.collect())
#去重,无需参数
rdd2 = rdd1.distinct()
#进行排序   参数:方法,排序方式,分区
final_rdd=rdd1.sortBy(方法,ascending=false,numPartitions=1)
#将rdd转换为list对象,即可以进行输出
rdd1.collect()
#对rdd进行两两聚合
rdd1.reduce(lambda a,b: a+b)
#取出rdd中前n个元素
rdd1.take(3)
#统计rdd中有多少条数据
rdd1.count()

sc.stop()



4、数据输出

需要下载hadoop安装包,解压,然后配置

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

os.environ['HADOOP_HOME']='解压文件的路径'

下载winutils.exe,并放入hadoop解压文件夹的bin目录

下载hadoop.dll,并放入system32文件夹内

要输出文件只有一个,则需要设置conf.set("spark.default.parallelism","1")

或者在创建rdd的时候设置rdd1 = sc.parallelize([1,2,3,4],numSlices=1),即numSlices=1

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

conf = SparkConf().setMaster("local[*]").setAppName("test_spark")
conf.set("spark.default.parallelism","1")
sc = SparkContext(conf=conf)



#输出到文件   输出的是文件夹,里面有多个文件
rdd3=sc.parallelize([1,2,3,4,5])
rdd3.saveAsTextFile("../data/oupt/test")

5、闭包

定义双层嵌套函数,内层函数可以访问外层函数的变量,将内层函数作为外层函数的返回,此内层函数就是闭包函数

在闭包函数中想要修改外部函数的变量值,需要用nonlocal声明这个外部变量

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

def account_create(initial_amount=0):
    def amt(num,deposit = True):
        nonlocal initial_amount
        if deposit:
            initial_amount+=num
            print(f"存款:+{num},账户余额:{initial_amount}")
        else:
            initial_amount -=num
            print(f"取款:-{num},账户余额:{initial_amount}")
    return amt

atm = account_create()
atm(100)
atm(200)
atm(-100)

6、装饰器

6.1 方法装饰器

装饰器其实也是一种闭包,其功能就是再不破坏目标函数原有的代码和功能的前提下,为目标函数增加新功能。

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

# 1、装饰器的一般写法(闭包)
def outer(func):
    def inner():
        print("我睡觉了......")
        func()
        print("我起床了......")
    return inner



def sleep():
    import random
    import time
    print("睡眠......")
    time.sleep(random.randint(1,5))
# print("我睡觉了......")
# sleep()
# print("我起床了......")

fn = outer(sleep)
fn()







# 2、装饰器的快捷写法(语法糖)
def outer(func):
    def inner():
        print("我睡觉了......")
        func()
        print("我起床了......")
    return inner

@outer
def sleep():
    import random
    import time
    print("睡眠......")
    time.sleep(random.randint(1,5))

sleep()

不定长参数: *args,**kwargs 表示可以传入任意的参数和键值对的参数,例如(1,2,3,age="18")

多装饰器的使用

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown



# 装饰器1
def check1(fn):
    def inner():
        print("登陆验证1.。。。")
        fn()
    return inner
# 装饰器2
def check2(fn):
    def inner():
        print("登陆验证2.。。。")
        fn()
    return inner

# 被装饰的函数
@check1
@check2  # 靠的最近的先起到装饰作用
def comment():
    print("发布言论")


comment()

带参数的装饰器

装饰器的外部函数只能传一个参数

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown



# 装饰器
def logging(flag):
    def check1(fn):
        def inner(num1,num2):
            if flag =="+":
                print("--正在努力加法计算---")
            elif flag=="-":
                print("--正在努力减法计算---")
            result = fn(num1,num2)
            return result
        return inner
    #返回装饰器
    return check1

# 被带有参数的装饰器装饰的函数
@logging('+')
def comment(a,b):
    result = a + b
    return result
    # print(result)


result = comment(1,3)
print(result)

6.2 类装饰器

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

# 定义一个类,实现_call_方法
class Check(object):
    def __init__(self,fn):
        self.__fn = fn
    def __call__(self, *args, **kwargs):
        print("我是call方法")
        self.__fn()

#被装饰的函数
@Check
def comment():
    print("发表言论")

comment()

property属性

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

# ======1、装饰器方式=======================
class Person(object):
    def __init__(self):
        self.__age = 0
    #获取属性
    @property
    def age(self):
        return self.__age
    #修改属性
    @age.setter
    def age(self,new_age):
        self.__age = new_age

# @property
p = Person()
print(p.age)
#修改属性
p.age = 100
print(p.age)


#  =====2、类属性方式=================================
class Person(object):
    def __init__(self):
        self.__age = 0
    #获取属性

    def get_age(self):
        return self.__age
    #修改属性

    def set_age(self,new_age):
        if new_age>=150:
            print("年龄错误")
        else:
            self.__age = new_age

    age = property(get_age,set_age)


p = Person()
print(p.age)
#修改属性
p.age = 100
print(p.age)

7、设计模式

7.1 单例模式

保证一个类只能有一个实例,并提供一个访问它的全局访问点

即创建一个实例后,不管在哪调用都是同一个

节省内存、节省创建对象的开销

7.2工厂模式

将对象的创建转换为由特定的工厂方法来创建

8 、多进程

进程优缺点:

优点:可以用多核

缺点:资源开销大

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import multiprocessing
import time

def work():
    for i in range(3):
        print("work",i)
        time.sleep(0.2)


def work2():
    for i in range(3):
        print("work2 ",i)
        time.sleep(0.2)


if __name__ == '__main__':
    work_process = multiprocessing.Process(target=work)
    work_process2 = multiprocessing.Process(target=work2)
    work_process.start()
    work_process2.start()

主进程会等待子进程结束才结束,设置进程守护,则可以让子进程跟着主进程一起结束

9、多线程

线程优缺点:

优点:资源开销小

缺点:不能使用多核

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import threading
import time

def work():
    for i in range(3):
        print("work",i)
        time.sleep(0.2)


def work2():
    for i in range(3):
        print("work2 ",i)
        time.sleep(0.2)



if __name__ == '__main__':
    work_thread = threading.Thread(target=work)
    work2_thread = threading.Thread(target=work2)
    work_thread.start()
    work2_thread.start()

主线程会等待子线程结束才结束,设置线程守护,则可以让子线程跟着主线程一起结束

设置 daemon=True 参数

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

work_thread = threading.Thread(target=work,daemon=True)

或者在start前(但是此方法已经过时)

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

work_thread.setDaemon(True)

线程间的执行顺序是无序的

获取线程信息

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

current_thread = threading.current_thread()

线程间共享全局变量,但是可能导致全局变量数据错误的问题

解决办法:线程同步去操作同一个变量

9.1互斥锁

对共享数据进行锁定,保证同一时刻只有一个线程去操作

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import threading

#全局变量
g_num = 0

# 对 g_num进行加操作
def sum_num1():
    #上锁
    mutex.acquire()
    for i in range(1000000):
        global g_num
        g_num +=1
    #解锁
    mutex.release()
    print("g_num1:",g_num)


# 对 g_num进行加操作
def sum_num2():
    # 上锁
    mutex.acquire()
    for i in range(1000000):
        global g_num
        g_num += 1
        # 解锁
    mutex.release()
    print("g_num2:", g_num)

if __name__ == '__main__':
    # 创建锁
    mutex = threading.Lock()
    #创建子线程
    sum1_thread = threading.Thread(target=sum_num1)
    sum2_thread = threading.Thread(target=sum_num2)

    #启动线程
    sum1_thread.start()
    sum2_thread.start()

9.2死锁

使用互斥锁的时候,要注意在合适的位置释放锁,不然就会导致死锁

10、TCP服务:socket

10.1、客户端

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import socket


if __name__ == '__main__':

    # 1、创建客户端套接字对象   AF_INET表四ipv4  SOCK_STREAM表示YCP传输协议类型
    tcp_client_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 2、和服务端套接字建立连接
    tcp_client_socket.connect(("192.168.233.1",8080))
    # 3、发送数据
    tcp_client_socket.send("你好!".encode(encoding="utf-8"))
    # 4、接收数据   recv会阻塞等待数据的到来    recv表示每次接收数据的大小,单位是字节
    recv_data = tcp_client_socket.recv(1024)
    print(recv_data.decode(encoding="utf-8"))
    # 5、关闭客户端套接字
    tcp_client_socket.close()

10.2 服务端

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import socket

if __name__ == '__main__':

    # 1、创建服务端套接字对象
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
 	#设置端口复用   不设置的话,断开后再连接会提示端口已经在用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
    # 2、绑定IP地址和端口
    # tcp_server_socket.bind(("192.168.233.1",8080))
    #第一个ip地址设置为“”,默认为本机ip地址
    tcp_server_socket.bind(("", 8080))
    # 3、设置监听   128:表示服务端等待排队连接的最大数量
    tcp_server_socket.listen(128)
    # 4、等待客户端的连接请求  accept阻塞等待 ,返回一个用以和客户端socket,客户端的地址
    conn_socket,ip_port = tcp_server_socket.accept()
    print("客户端地址:",ip_port)
    # 5、接收数据
    recv_data = conn_socket.recv(1024)
    print("接收到的数据:",recv_data.decode())
    # 6、发送数据
    conn_socket.send("客户端你的数据我接收到了".encode())
    # 7、关闭套接字
    conn_socket.close()
    tcp_server_socket.close()

当客户端的套接字调用close后,服务器端的revc会解阻塞,返回的数据长度为0,服务端可以通过返回数据的长度来判断客户端是否已经下线,反之服务端关闭套接字,客户端的recv也会解阻塞,返回的数据长度也为0

10.3 多任务TCP服务端

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import socket

if __name__ == '__main__':

    # 1、创建服务端套接字对象
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #设置端口复用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
    # 2、绑定IP地址和端口
    # tcp_server_socket.bind(("192.168.233.1",8080))
    #第一个ip地址设置为“”,默认为本机ip地址
    tcp_server_socket.bind(("", 8080))
    # 3、设置监听   128:表示服务端等待排队连接的最大数量
    tcp_server_socket.listen(128)

    while True:
        # 4、等待客户端的连接请求  accept阻塞等待 ,返回一个用以和客户端socket,客户端的地址
        conn_socket,ip_port = tcp_server_socket.accept()
        print("客户端地址:",ip_port)
        # 5、接收数据
        recv_data = conn_socket.recv(1024)
        print("接收到的数据:",recv_data.decode())
        # 6、发送数据
        conn_socket.send("客户端你的数据我接收到了".encode())
        # 7、关闭套接字
        conn_socket.close()

    tcp_server_socket.close()

上面方式需要一个客户端完成一个完整请求后,其他的请求才能进入,无法同时处理多个客户端的请求,所以需要使用下面多线程的方式

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import socket
import threading

#处理客户端函数
def handle_client(conn_socket):
    # 5、接收数据
    recv_data = conn_socket.recv(1024)
    print("接收到的数据:", recv_data.decode())
    # 6、发送数据
    conn_socket.send("客户端你的数据我接收到了".encode())
    # 7、关闭套接字
    conn_socket.close()

if __name__ == '__main__':

    # 1、创建服务端套接字对象
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #设置端口复用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
    # 2、绑定IP地址和端口
    # tcp_server_socket.bind(("192.168.233.1",8080))
    #第一个ip地址设置为“”,默认为本机ip地址
    tcp_server_socket.bind(("", 8080))
    # 3、设置监听   128:表示服务端等待排队连接的最大数量
    tcp_server_socket.listen(128)

    while True:
        # 4、等待客户端的连接请求  accept阻塞等待 ,返回一个用以和客户端socket,客户端的地址
        conn_socket,ip_port = tcp_server_socket.accept()
        print("客户端地址:",ip_port)
        # 使用多线程去接收多个客户端的请求
        sub_thread = threading.Thread(target=handle_client,args=(conn_socket,))
        sub_thread.start()

    tcp_server_socket.close()

11、web服务器

11.1静态web服务器

使用python自带的webfwq使用 python3 -m http.server 端口号这个命令即可,端口号可以省略,则使用默认端口号

自己开发

单用户请求,多任务需要改成多线程

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import socket



if __name__ == '__main__':

    # 1、创建服务端套接字对象
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #设置端口复用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
    # 2、绑定IP地址和端口
    # tcp_server_socket.bind(("192.168.233.1",8080))
    #第一个ip地址设置为“”,默认为本机ip地址
    tcp_server_socket.bind(("", 8080))
    # 3、设置监听   128:表示服务端等待排队连接的最大数量
    tcp_server_socket.listen(128)

    while True:
        # 4、等待客户端的连接请求  accept阻塞等待 ,返回一个用以和客户端socket,客户端的地址
        conn_socket,ip_port = tcp_server_socket.accept()
        print("客户端地址:",ip_port)
        # 5、接收数据
        client_request_data = conn_socket.recv(1024).decode()
        print("接收到的数据:", client_request_data)
        # 获取用户请求资源的路径
        request_data = client_request_data.split(" ")
        print(request_data)
        #请求资源路径
        request_path = request_data[1]
        if request_path=="/":
            request_path = "/index.html"
            
        # 读取固定页面数据,把页面数据组装成http响应报文数据发送给浏览器
        try:
            with open("./static"+request_path,"rb") as f:
                filer_data = f.read()
        except Exception as e:
            #返回404错误数据
            # 应答行
            response_line = "HTTP/1.1 404 Not Found\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = "404 Not Found sorry"
            # 应答数据
            response_data = (response_line + response_header + "\r\n" + response_body).encode()
            # 6、发送数据
            conn_socket.send(response_data)
        else:
            # 应答行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            #应答体
            response_body = filer_data
            # 应答数据
            response_data = (response_line+response_header+"\r\n").encode()+response_body
            # 6、发送数据
            conn_socket.send(response_data)
        finally:
            # 7、关闭套接字
            conn_socket.close()

    tcp_server_socket.close()

多线程实现多客户端同时请求

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import socket
import threading

def handle_client_request(conn_socket):
    # 5、接收数据
    client_request_data = conn_socket.recv(1024).decode()
    print("接收到的数据:", client_request_data)
    # 获取用户请求资源的路径
    request_data = client_request_data.split(" ")
    print(request_data)
    #判断客户端是否关闭
    if len(request_data)==1:
        conn_socket.close()
        return 
    # 请求资源路径
    request_path = request_data[1]
    if request_path == "/":
        request_path = "/index.html"

    # 读取固定页面数据,把页面数据组装成http响应报文数据发送给浏览器
    try:
        with open("./static" + request_path, "rb") as f:
            filer_data = f.read()
    except Exception as e:
        # 返回404错误数据
        # 应答行
        response_line = "HTTP/1.1 404 Not Found\r\n"
        # 应答头
        response_header = "Server:pwb\r\n"
        # 应答体
        response_body = "404 Not Found sorry"
        # 应答数据
        response_data = (response_line + response_header + "\r\n" + response_body).encode()
        # 6、发送数据
        conn_socket.send(response_data)
    else:
        # 应答行
        response_line = "HTTP/1.1 200 OK\r\n"
        # 应答头
        response_header = "Server:pwb\r\n"
        # 应答体
        response_body = filer_data
        # 应答数据
        response_data = (response_line + response_header + "\r\n").encode() + response_body
        # 6、发送数据
        conn_socket.send(response_data)
    finally:
        # 7、关闭套接字
        conn_socket.close()

if __name__ == '__main__':

    # 1、创建服务端套接字对象
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    #设置端口复用
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,True)
    # 2、绑定IP地址和端口
    # tcp_server_socket.bind(("192.168.233.1",8080))
    #第一个ip地址设置为“”,默认为本机ip地址
    tcp_server_socket.bind(("", 8080))
    # 3、设置监听   128:表示服务端等待排队连接的最大数量
    tcp_server_socket.listen(128)

    while True:
        # 4、等待客户端的连接请求  accept阻塞等待 ,返回一个用以和客户端socket,客户端的地址
        client_socket,ip_port = tcp_server_socket.accept()
        print("客户端地址:",ip_port)

        sub_thread  = threading.Thread(target=handle_client_request,args=(client_socket,))
        sub_thread.start()


    # tcp_server_socket.close()   不注释的话一个请求完成就会关闭程序

11.2 面向对象开发

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import socket
import threading


class HttpWebServer:
    def __init__(self):
        # 1、创建服务端套接字对象
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置端口复用
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 2、绑定IP地址和端口
        # tcp_server_socket.bind(("192.168.233.1",8080))
        # 第一个ip地址设置为“”,默认为本机ip地址
        self.tcp_server_socket.bind(("", 8080))
        # 3、设置监听   128:表示服务端等待排队连接的最大数量
        self.tcp_server_socket.listen(128)

    def handle_client_request(self,conn_socket):
        # 5、接收数据
        client_request_data = conn_socket.recv(1024).decode()
        print("接收到的数据:", client_request_data)
        # 获取用户请求资源的路径
        request_data = client_request_data.split(" ")
        print(request_data)
        # 判断客户端是否关闭
        if len(request_data) == 1:
            conn_socket.close()
            return
        # 请求资源路径
        request_path = request_data[1]
        if request_path == "/":
            request_path = "/index.html"

        # 读取固定页面数据,把页面数据组装成http响应报文数据发送给浏览器
        try:
            with open("./static" + request_path, "rb") as f:
                filer_data = f.read()
        except Exception as e:
            # 返回404错误数据
            # 应答行
            response_line = "HTTP/1.1 404 Not Found\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = "404 Not Found sorry"
            # 应答数据
            response_data = (response_line + response_header + "\r\n" + response_body).encode()
            # 6、发送数据
            conn_socket.send(response_data)
        else:
            # 应答行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = filer_data
            # 应答数据
            response_data = (response_line + response_header + "\r\n").encode() + response_body
            # 6、发送数据
            conn_socket.send(response_data)
        finally:
            # 7、关闭套接字
            conn_socket.close()

    def start(self):
        while True:
            # 4、等待客户端的连接请求  accept阻塞等待 ,返回一个用以和客户端socket,客户端的地址
            client_socket, ip_port = self.tcp_server_socket.accept()
            print("客户端地址:", ip_port)

            sub_thread = threading.Thread(target=self.handle_client_request, args=(client_socket,))
            sub_thread.start()


if __name__ == '__main__':
    # 创建服务器对象
    my_web_server = HttpWebServer()
    my_web_server.start()

命令行启动动态绑定端口号 导入import sys

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

import socket
import threading
import sys

class HttpWebServer:
    def __init__(self,port):
        # 1、创建服务端套接字对象
        self.tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # 设置端口复用
        self.tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
        # 2、绑定IP地址和端口
        # tcp_server_socket.bind(("192.168.233.1",8080))
        # 第一个ip地址设置为“”,默认为本机ip地址
        self.tcp_server_socket.bind(("", port))
        # 3、设置监听   128:表示服务端等待排队连接的最大数量
        self.tcp_server_socket.listen(128)

    def handle_client_request(self,conn_socket):
        # 5、接收数据
        client_request_data = conn_socket.recv(1024).decode()
        print("接收到的数据:", client_request_data)
        # 获取用户请求资源的路径
        request_data = client_request_data.split(" ")
        print(request_data)
        # 判断客户端是否关闭
        if len(request_data) == 1:
            conn_socket.close()
            return
        # 请求资源路径
        request_path = request_data[1]
        if request_path == "/":
            request_path = "/index.html"

        # 读取固定页面数据,把页面数据组装成http响应报文数据发送给浏览器
        try:
            with open("./static" + request_path, "rb") as f:
                filer_data = f.read()
        except Exception as e:
            # 返回404错误数据
            # 应答行
            response_line = "HTTP/1.1 404 Not Found\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = "404 Not Found sorry"
            # 应答数据
            response_data = (response_line + response_header + "\r\n" + response_body).encode()
            # 6、发送数据
            conn_socket.send(response_data)
        else:
            # 应答行
            response_line = "HTTP/1.1 200 OK\r\n"
            # 应答头
            response_header = "Server:pwb\r\n"
            # 应答体
            response_body = filer_data
            # 应答数据
            response_data = (response_line + response_header + "\r\n").encode() + response_body
            # 6、发送数据
            conn_socket.send(response_data)
        finally:
            # 7、关闭套接字
            conn_socket.close()

    def start(self):
        while True:
            # 4、等待客户端的连接请求  accept阻塞等待 ,返回一个用以和客户端socket,客户端的地址
            client_socket, ip_port = self.tcp_server_socket.accept()
            print("客户端地址:", ip_port)

            sub_thread = threading.Thread(target=self.handle_client_request, args=(client_socket,))
            sub_thread.start()

def main():
    # 获取执行python程序的终端命令行参数
    print(sys.argv)
    if len(sys.argv != 2:
        print("格式错误 python3 xxx.py 9090")
        return
    #判断是否整型
    if not sys.argv[1].isdigit():
        print("格式错误 python3 xxx.py 9090")
        return
    port = sys.argv[1]

    # 创建服务器对象
    my_web_server = HttpWebServer(port)
    my_web_server.start()


if __name__ == '__main__':
   main()

12、with语句和上下文管理

作用:例如文件操作时,自动调用关闭文件操作,即使出现异常也会自动调用关闭

--javascripttypescriptshellbashsqljsonhtmlcssccppjavarubypythongorustmarkdown

with open("1.txt","r") as f:
    rdata = f.read()
    print(rdata)

13、正则表达式

14、连接sqlserver

pip install pyodbc

15、生成和安装项目锁使用的包

生成包版本文件: pip freeze > requirements.txt

部署时安装: pip install -r requirements.txt

;