提示:记录一些vim编辑环境下常用命令以及pyhon3高级编程

目录

一.python3网络编程

1.udp

1.udp实现从linux发送数据到windows

2.接收数据到ubuntu

3.使用同一个套接字完成收发信息

4.一个udp聊天器案例

2.tcp实现

1.tcp-client发送信息青春版

2.tcp-server青春版

3.循环为多个客户端服务的服务器青春版

4.升级版的循环服务的服务器

5.案例-文件下载器

二.多任务

1.多任务(线程实现)

1.多任务-线程

2.继承Thread类完成多任务

3.函数里修改全局变量

4.互斥锁解决资源竞争问题

5.多任务实现udp聊天器

1.多任务(进程实现)

1.使用进程完成多任务

2.利用队列完成多任务进程之间的通信

3.案例-复制文件jia里所有文件青春版

4.案例-带进度条的文件夹拷贝器

3.多任务(协程实现)

1.迭代器-自己定义的类进行迭代青春版

2.迭代器-自己的类进行迭代

3.迭代器实现多任务(Fibonacci为例子)

4.生成器-实现斐波那契数列

5.生成器的一些知识

6.生成器send()实现多任务

7.通过yield完成多任务

8.greenlet多任务

9.gevent完成多任务

10.gevent多任务-2

11.案例-图片下载器

三.web服务器v3.1

1.正则表达式简介

1.正则判断变量名是否合理

2.正则判断常用邮箱地址

2.http

1.实现简单的http服务器

2.根据客户端需要完成http服务器

3.返回index页面http

4.使用多进程完成http服务器

5.使用多线程完成http

6.协程完成http服务器

7.单进程单线程非堵塞并发完成http服务器

8.单进程单线程非堵塞长连接

9.epoll实现http服务器


一.python3网络编程

1.udp

1.udp实现从linux发送数据到windows

windows编码是("gbk")

linux('utf-8')

import socket
def main():
        udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        while True:
            sent_data = input("请输入您需要发送的信息")
            if sent_data == 'exit':break
            udp_socket.sendto(sent_data.encode('utf-8'),("172.21.126.225",8080))
        udp_socket.close()

if __name__ =='__main__':
        main()

解码用decode

编码用encode

发信息基本步骤:1.创建套接字

                             2.输入需要发送的信息

                             3.发送信息

                             4.关闭套接字

2.接收数据到ubuntu

收信息基本步骤:1.创建套接字

                             2.绑定端口号

                             3.调用函数recvfrom() 第一个返回值是信息,第二个是对方的地址

                             4.关闭套接字

import socket
def main():
        # 创建套接字
        udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        # 绑定端口号
        local_addr = ("",4657)
        udp_socket.bind(local_addr)
        recv_data = udp_socket.recvfrom(1024)
        recv_msg = recv_data[0]  # 接受的信息
        recv_addr = recv_data[1] # 发送者的地址信息
        print(f"{recv_addr}:{recv_msg}")
        # udp_socket.sendto(b"haha",("172.21.126.225",8080))
        udp_socket.close()

if __name__ =='__main__':
        main()

3.使用同一个套接字完成收发信息

import socket
def main():
        # 创建套接字
        udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
        # 获取对方的ip/port
        dest_ip = input("请输入对方的ip:")
        dest_port = int(input("请输入对方的port:"))
        # 从键盘获取数据
        send_data = input("请输入要发送的数据:")

        # 可以使用套接字收发数据
        udp_socket.sendto(send_data.encode("utf-8"),(dest_ip,dest_port))



        # 绑定端口号
        # local_addr = ("",4657)
        # udp_socket.bind(local_addr)
        # 接手数据
        recv_data = udp_socket.recvfrom(1024)
        recv_msg = recv_data[0]  # 接受的信息
        recv_addr = recv_data[1] # 发送者的地址信息
        print(f"{recv_addr}:{recv_msg}")
        # udp_socket.sendto(b"haha",("192.168.220.1",8080))
        udp_socket.close()

if __name__ =='__main__':
        main()

4.一个udp聊天器案例

import socket

def send_msg(udp_socket):
        """发送消息"""
        dest_ip = input("请输入对方的ip:")
        dest_port = int(input("请输入对方的port:"))
        send_data = input("请输入要发送的数据:")
        # 可以使用套接字收发数据
        udp_socket.sendto(send_data.encode("utf-8"),(dest_ip,dest_port))


def recv_msg(udp_socket):
        """接收数据"""
        recv_data = udp_socket.recvfrom(1024)
        recv_msg = recv_data[0].decode("gbk")  # 接受的信息
        recv_addr = recv_data[1] # 发送者的地址信息
        print(f"{recv_addr}:{recv_msg}")

def main():
        # 创建套接字
        udp_socket = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)

        #绑定信息
        udp_socket.bind(("",7788))
        # 获取对方的ip/port
        # dest_ip = input("请输入对方的ip:")
        # dest_port = int(input("请输入对方的port:"))
        # 从键盘获取数据
        while True:
            print("-----dup聊天器-----")
            print("1:发送消息")
            print("2:接收消息")
            print("0:退出聊天器")
            op = input("请输入功能:")
            if op == "1":
                #发送消息
                send_msg(udp_socket)
            elif op == "2":
                # 接收数据并显示   
                recv_msg(udp_socket)
            elif op == '0':break
            else:
                print("输入有误")

        # 绑定端口号
        # local_addr = ("",4657)
        # udp_socket.bind(local_addr)
            # 接收数据
        # udp_socket.sendto(b"haha",("192.168.220.1",8080))
        udp_socket.close()

if __name__ =='__main__':
    main()                                                              21,1          Top

2.tcp实现

tcp分为客户端和服务器

1.tcp-client发送信息青春版

(1)先创建一个tcp套接字

        tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

        不同于udp,socket()函数的第二个参数里更改为SOCK_STREAM

(2)然后调用connect函数调用服务器,将服务器的ip地址个port端口以元组形式传进connect里

(3)接着进行收发信息操作:发信息用send函数

(4)最后关闭套接字

import socket


def main():
    # 1创建tcp套接字
    tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 2链接服务器
    server_ip = input("请输入需要连接的服务器的ip:")
    server_port = int(input("请输入此服务器的port:"))
    server_addr = (server_ip,server_port)
    tcp_socket.connect(server_addr)

    # 3发送/接收数据
    send_data = input("请输入要发送的信息:")
    tcp_socket.send(send_data.encode("utf-8"))

    # 4关闭套接字
    tcp_socket.close()



if __name__ == '__main__':
    main()

2.tcp-server青春版

(1)创建套接字

(2)绑定本地port,因为是服务器所以要帮定

(3)调用listen(128)函数,是服务器处于被动状态,128可以理解为最多有128个客户端链接

(4)等待客户端的链接,调用accept()函数,会有两个返回值,第一个表示客户端的套接字,第二个是客户端的地址信息

(5)调用recv(1024)接受信息1024是最大字节数

(6)调用send()回信息,告诉客户端链接成功

(7)关闭套接字,先关闭客户端的套接字,然后是服务器的套接字

import socket


def main():
    # 1 买个手机 (创建套接字)
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 2 插个手机卡 (绑定本地信息 bind)
    tcp_server_socket.bind(("",7890))
    # 3 将手机设置为响铃模式(让默认的套接字由主动变为被动listen)
    tcp_server_socket.listen(128)
    # 4 等待别人打电话 (等待客户端的链接accept)
    print("-----1-----")
    new_client_socket,client_addr = tcp_server_socket.accept()
    print("-----2-----")

    print(client_addr)

    # 接受客户短发送过来的请求
    recv_data = new_client_socket.recv(1024)
    print(recv_data)

    # 回送一部分数据给客户端
    new_client_socket.send("hhhhhh-----ok------".encode('utf-8'))

    # 关闭套接字
    new_client_socket.close()
    tcp_server_socket.close()
if __name__ == "__main__":
    main()

3.循环为多个客户端服务的服务器青春版

(1)创建套接字

(2)绑定ip和port ip一般用空字符串表示

(3)调用listen

(4)进入循环,accept循环接受客户端的链接,客户端的套接字关闭也要在循环里

(5)关闭服务器的套接字

import socket

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 绑定ip 和 port
    tcp_server_socket.bind(("",4111))
    # 被动接受数据
    tcp_server_socket.listen(128)

    while True:
        print("-----1-----\n等待一个客户端到来")
        # 接收数据
        new_client_socket,client_addr = tcp_server_socket.accept()

        print("-----2-----\n客户端来喽")
        print(f"地址为:{client_addr}")
        # 读取信息
        recv_data = new_client_socket.recv(1024)


        # 回送信息给客户端
        print(f"信息是:{recv_data}")
        new_client_socket.send("----给我成功----".encode('utf-8'))

        # 关闭套接字
        new_client_socket.close()
        print("服务结束")
    tcp_server_socket.close()

if __name__ == "__main__":
    main()
~

4.升级版的循环服务的服务器

大体步骤和3类似,循环体内又加了一个循环,recv_data = new_cilent_socket.recv(1024)

为空时,表示客户端断开链接,升级版可以一直接收一个客户端的信息。

import socket

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 绑定ip 和 port
    tcp_server_socket.bind(("",4111))
    # 被动接受数据
    tcp_server_socket.listen(128)

    while True:
        print("-----1-----\n等待一个客户端到来")
        # 接收数据
        new_client_socket,client_addr = tcp_server_socket.accept()

        print("-----2-----\n客户端来喽")
        print(f"地址为:{client_addr}")
        while True:
            # 读取信息
            recv_data = new_client_socket.recv(1024)

            # 回送信息给客户端
            print(f"客户端的请求是:{recv_data}")
            if recv_data:
                new_client_socket.send("----给我成功----".encode('utf-8'))
            else:break
        # 关闭套接字
        new_client_socket.close()
        print("服务结束")
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

5.案例-文件下载器

先是客户端

(1)创建套接字。。。。。。。。到第四步

(4)获取文件的名字

(5)将文件的名字发送到服务器里

(6)等待服务器响应

(7)移步服务器

import socket

def main():
    # 1.创建套接字
    tcp_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 2.获取服务器ip port
    dest_ip = input("请输入下载服务器的ip:")
    dest_port = int(input("请输入下载服务器的port:"))
    # 3.链接服务器
    tcp_socket.connect((dest_ip,dest_port))

    # 4.获取下载的文件名称
    download_file_name = input("请输入要下载的文件名字:")

    # 5.将文件名字发送到服务器
    tcp_socket.send(download_file_name.encode("utf-8"))

    # 6.接收文件中的数据
    recv_data = tcp_socket.recv(1024)  # 1024 * 1024 = 1M

    if recv_data:
     # 7.保存接收到的数据到一个文件中
        with open("[新]" + download_file_name,'wb') as f:
            f.write(recv_data)
    else:print("没有要下载的文件:")
    # 8.关闭套接字
    tcp_socket.close()

if __name__ == "__main__":
    main()
~                                                                               
~

服务器:

循环体内等待客户端链接,接收到一个客户端,send_file_2_client里接收服务器名字,先把文件内容定义为空,try内,打开文件,如果没有要下载的文件就打印结果,最后if 内,如果有文件就将内容发送给客户端,客户端接收到内容,就创建一个文件并将内容写入,否则print("没有要下载的文件"),最后关闭套接字

import socket

def send_file_2_client(new_client_socket,client_addr):
    # 读取信息
    # 1.接受客户端需要的文件名
    file_name = new_client_socket.recv(1024).decode('utf-8')
    file_content = None
    # 2.打开这个文件,读取数据
    try:
        f = open(file_name,'rb')
        file_content = f.read()
        f.close()
    except Exception as ret:
        print("没有要下载的文件(%s)" % file_name)
    # 3.发送文件的数据给客户端

    if file_content:
        print(f"客户端{client_addr}需要下载的文件是:{file_name}")
        new_client_socket.send(file_content)


def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    # 绑定ip 和 port
    tcp_server_socket.bind(("",4111))
    # 被动接受数据
    tcp_server_socket.listen(124)

    while True:
        # 接收数据
        new_client_socket,client_addr = tcp_server_socket.accept()

        print(f"地址为:{client_addr}")
        # 调用函数完成服务 
        send_file_2_client(new_client_socket,client_addr)
        # 关闭套接字
        new_client_socket.close()
    tcp_server_socket.close()

if __name__ == "__main__":
    main()
~

二.多任务

1.多任务(线程实现)

1.多任务-线程

定义两个函数sing和dance

通过导入模块threading

里面有个类Thread()有两个参数,第一个表示目标函数,第二个表示函数的参数,用元组表示

创建对象后调用start来实现两个函数并发执行

import time
import threading


def sing():
    '''正在唱歌'''
    for i in range(5):
        print("-----正在唱歌-----")
        time.sleep(1)


def dance():
    '''正在跳舞'''
    for i in range(10):
        print('-----正在跳舞-----')
        time.sleep(1)


def main():
    t1 = threading.Thread(target = sing)
    t2 = threading.Thread(target = dance)
    t1.start()
    t2.start()
    while True:
        # 查看线程数    
        print(threading.enumerate())
        if len(threading.enumerate()) == 1:break
        time.sleep(1)


if __name__ == "__main__":
    main()
~                                                                              
~

2.继承Thread类完成多任务

import threading
import time


class Mythread(threading.Thread):
    def run(self):
        self.login()
        self.register()
        for i in range(3):
            time.sleep(1)
            msg = "I'm" + self.name + ' @ ' +str(i)
            print(msg)


    def login(self):
        for i in range(5):
            print("正在等录" + str(i))
            time.sleep(1)


    def register(self):
        for i in range(10):
            print("正在注册" + str(i))
            time.sleep(1)

if __name__ == "__main__":
    t = Mythread()
    t.start()
~

3.函数里修改全局变量

调用threading的方法,多线程之间共享全局变量

import threading
import time

nums = [11,22,33]


def test1(temp):
    temp.append(44)
    print(f"{temp}")


def test2(temp):
    temp.append(44)
    print(temp)


if __name__ == "__main__":
    t1 = threading.Thread(target = test1,args = (nums,))
    t2 = threading.Thread(target = test2,args = (nums,))

    t2.start()
    t1.start()

4.互斥锁解决资源竞争问题

使用多线程对全局变量进行修改时,如果调用次数很多,会产生资源竞争问题,

可以定义一个互斥锁mutex = threading.Lock()

acquire表示上锁,release表示解锁

上锁到解锁之间只允许一个线程运行

import time
import threading

g_num = 0
mutex = threading.Lock()


def test1(num):
    global g_num
    mutex.acquire()
    for i in range(num):
        g_num += 1
    mutex.release()
    print("----------in test1 g_num = %d----------" % g_num)


def test2(num):
    global g_num
    mutex.acquire()
    for i in range(num):
        g_num += 1
    mutex.release()
    print("----------in test2 g_num = %d----------" % g_num)

def main():
    t1 = threading.Thread(target = test1,args = (1000000,))
    t2 = threading.Thread(target = test2,args = (1000000,))

    t1.start()
    t2.start()
    time.sleep(5)
    print("----------in main g_num = %d----------" % g_num)

if __name__ == "__main__":
    main()

5.多任务实现udp聊天器

定义两个函数,一个接收信息,一个发送信息,之前的聊天器很死板,只能发一次收一次,有了多任务,就可以实现收发一起执行,不一样的是,最后不能关闭套接字,因为不知到什么时候聊天结束。

import socket
import threading
 
 
def recv_meassage(udp_socket):
    '''接收信息并显示'''
    while True:
        recv_data = udp_socket.recvfrom(1024)
        recv_msg = recv_data[0].decode('utf-8')
        recv_addr = recv_data[1]
        print(f"\n{recv_addr}发来了信息:{recv_msg}")
 
 
def send_msg(udp_socket ,dest_ip, dest_port):
    '''发送信息'''
    while True:
        send_data = input("请输入您要发送的信息:")
        udp_socket.sendto(send_data.encode('utf-8'), (dest_ip, dest_port))
 
 
def main():
    # 创建套接字
    udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
 
    # 绑定端口
    udp_socket.bind(('',3555))
    dest_ip = input("请输入对方的ip地址:")
    dest_port = int(input("请输入对方ip地址的端口port:"))
 
    t_send = threading.Thread(target = send_msg, args = (udp_socket, dest_ip, dest_port))
    t_recv = threading.Thread(target = recv_meassage, args = (udp_socket,))
 
    t_send.start()
    t_recv.start()
 
    # 关闭套接字
    # udp_socket.close()
 
 
if __name__ == "__main__":
    main()
————————————————
版权声明:本文为CSDN博主「小白来巡山^_^」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:

1.多任务(进程实现)

1.使用进程完成多任务

与线程类似,进程实现多任务需要导入模块 multiprocessing

不过,进程之间不共享全局变量,Process这个类和Thread一样,大致流程与线程实现多任务类似。

import time
import multiprocessing


num = 0

def test1(n):
    global num
    for i in range(n):
        num += 1
        print(f"1------{i}------")


def test2(n):
    global num
    for i in range(n):
        num += 1
        print(f"2-----{i}-----")


def main():
    p1 = multiprocessing.Process(target = test1, args = (100,))
    p2 = multiprocessing.Process(target = test2, args = (200,))

    p1.start()
    p2.start()
    time.sleep(10)
    print(num)


if __name__ == "__main__":
    main()

2.利用队列完成多任务进程之间的通信

需要创建一个实例对象q = multiprocessing.Queue()

并把q当作参数传进需要完成通信的子进程中去,队列是先进先出,向队列传数据用put,取数据用get,可以用p.empty()判断队列是否为空,p.full()判断队列是否满

import multiprocessing


def download_from_web(q):
    '''下载数据'''
    data = [11,22,33,44]
    #相队列中写入数据
    for temp in data:
        q.put(temp)
    print(f'{data}-----下载器已经下载完了数据并存入到队列中-----')


def analysis_data(q):
    '''数据处理'''
    # 从队列中获取数据病并模拟处理
    waitting_analysis_data = list()
    while True:
        data = q.get()
        waitting_analysis_data.append(data)

        if q.empty():break
    print(waitting_analysis_data)


def main():
    # 1.创建一个队列
    q = multiprocessing.Queue()
    p1 = multiprocessing.Process(target = download_from_web, args = (q,))
    p2 = multiprocessing.Process(target = analysis_data ,args = (q,))

    p1.start()
    p2.start()

if __name__ =="__main__":
    main()

3.案例-复制文件jia里所有文件青春版

用到了os模块里的mkdir创建文件夹,参数为文件夹的名字

os.listdir()获取名称为参数名称的文件夹里的所有文件名称,返回值是一个列表

引入新东西,进程池

po = multiprocessing.Pool(5)

参数表示一个进程池里最多可yi容纳五个进程

调用方法po.apply_async(copy_file ,args = (''''''''))向进程池里传入进程

close()关闭

join()让进程池里的进程执行完

函数里面 显示读取文件里的内容,再把内容写进新文件夹里文件里,完成拷贝

import os
import multiprocessing


def copy_file(file_name, new_folder_name, old_folder_name):
    print(file_name)
    f1 = open(old_folder_name + '/' + file_name, 'rb')
    f_content = f1.read()
    f1.close()
    f2 = open(new_folder_name + '/' + file_name,'wb')
    f2.write(f_content)
    f2.close()

def main():
    # 获取要下载的文件夹的名字
    old_folder_name = input("请输入要复制的文件夹的名字:")

    # 创建一个新的文件夹
    new_folder_name = old_folder_name + "[复件]"
    try:
        os.mkdir(new_folder_name)
    except:pass

    # 获取文件夹里所有文件的名字
    file_names = os.listdir(old_folder_name)

    # 创建进程池
    po = multiprocessing.Pool(5)

    # 向进程chi里添加copy文件的任务
    for file_name in file_names:
        po.apply_async(copy_file, args = (file_name, new_folder_name, old_folder_name))

    po.close()
    po.join()
    # 复制原文件夹的文件,到新文件夹里去



if __name__ == "__main__":
    main()

4.案例-带进度条的文件夹拷贝器

要想实现进度条,实现主进程和子进程之间的通信,要用到队列,multiprocessing.Manager().Queue(),将队列以参数形式传入函数里,没下载好一个文件就put以下,主进程里,每get一下就输出一个进度,进度值为下载好的文件数除以总的文件数,不用调用join()因为循环一定能保证子进程执行完毕,最后break

mport os
import multiprocessing


def copy_file(q, file_name, new_folder_name, old_folder_name):
    # print(file_name)
    f1 = open(old_folder_name + '/' + file_name, 'rb')
    f_content = f1.read()
    f1.close()
    f2 = open(new_folder_name + '/' + file_name, 'wb')
    f2.write(f_content)
    f2.close()
    # 如果拷贝完了队列就像队列中写入消息
    q.put(file_name)

def main():
    # 获取要下载的文件夹的名字
    old_folder_name = input("请输入要复制的文件夹的名字:")

    # 创建一个新的文件夹
    new_folder_name = old_folder_name + "[复件]"
    try:
        os.mkdir(new_folder_name)
    except:pass

    # 获取文件夹里所有文件的名字
    file_names = os.listdir(old_folder_name)

    # 创建进程池
    po = multiprocessing.Pool(5)

    # 创建队列
    q = multiprocessing.Manager().Queue()

    # 向进程chi里添加copy文件的任务
    for file_name in file_names:
        po.apply_async(copy_file, args = (q, file_name, new_folder_name, old_folder_name))

po.close()
    # po.join()
    all_file_num = len(file_names)
    now_file_num = 0
    while True:
        q.get()
        now_file_num += 1
        print('拷贝进度:%.2f%%' % (now_file_num * 100 / all_file_num))
        if now_file_num >= all_file_num:break
    # 复制原文件夹的文件,到新文件夹里去



if __name__ == "__main__":
    main()

3.多任务(协程实现)

1.迭代器-自己定义的类进行迭代青春版

from collections import Iterable,Iterator
import time

class Classmate(object):
    def __init__(self):
        self.names = list()

    def add(self,name):
        self.names.append(name)

    def __iter__(self):
        return ClassIterator(self)


class ClassIterator():
    def __init__(self,obj):
        self.obj = obj

    def __iter__(self):
        pass

    def __next__(self):
        return self.obj.names[0]


classmate = Classmate()
classmate.add('张三')
classmate.add('李四')
classmate.add('王五')

# print("判断classmate是否是可以迭代的对象:", isinstance(classmate, Iterable))

# classmate_iterator = iter(classmate)
# print("判断classmate_iterator是否是迭代器:", isinstance(classmate_iterator, Iterator))
# print(next(classmate_iterator))


for temp in classmate:
    print(temp)
    time.sleep(1)
~

2.迭代器-自己的类进行迭代

将Classmate类里添加 __iter__ 和 __next__类 完成迭代器

from collections.abc import Iterable,Iterator
import time

class Classmate(object):
    def __init__(self):
        self.names = list()
        self.current_num = 0

    def add(self,name):
        self.names.append(name)

    def __iter__(self):
        return self

    def __next__(self):
        if self.current_num < len(self.names):
            ret = self.names[self.current_num]
            self.current_num += 1
            return ret
        else:
            raise StopIteration


classmate = Classmate()
classmate.add('张三')
classmate.add('李四')
classmate.add('王五')

# print("判断classmate是否是可以迭代的对象:", isinstance(classmate, Iterable))

# classmate_iterator = iter(classmate)
# print("判断classmate_iterator是否是迭代器:", isinstance(classmate_iterator, Iterator))
# print(next(classmate_iterator))


for temp in classmate:
    print(temp)
    time.sleep(1)
~                                                                                   
~

3.迭代器实现多任务(Fibonacci为例子)

迭代器的优点:相对于list()创建列表,迭代器占用的内存非常小

class Fibonacci():
    def __init__(self,all_num):
        self.all_num = all_num
        self.a = 0
        self.b = 1
        self.current_num = 0

    def __iter__(self):
        return self

    def __next__(self):
        if self.all_num > self.current_num:
            ret = self.a
            self.a ,self.b = self.b, self.a + self.b
            self.current_num += 1
            return ret
        else:raise StopIteration

f = Fibonacci(10)

for num in f:
    print(num)

4.生成器-实现斐波那契数列

在函数里只要有yield就不是函数了,是生成器,创建对象obj,调用next(obj)调取a的值

def create_num(all_num):
    print('------1------')
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        print('------2------')
        yield a
        # print(a)
        print('------3------')
        a, b = b, a + b
        current_num += 1
# 如果函数有一个yield语句,这个函数就不是函数了,成为了一个生成器的模板,调用create_num时,生成器是一种特殊的迭代器,创建了一个生成器的对象


obj = create_num(10)
ret = next(obj)
print(ret)
ret = next(obj)
print(ret)
# for i in obj:
#     print(i)
~                                                                                   
~

5.生成器的一些知识

循环读取数据,当读不出来是,抛出一场 e.value为生成器的返回值

def create_num(all_num):
    print('------1------')
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        print('------2------')
        yield a
        # print(a)
        print('------3------')
        a, b = b, a + b
        current_num += 1
    return 'ok------ok'
# 如果函数有一个yield语句,这个函数就不是函数了,成为了一个生成器的模板,调用create_num时,生成器是一种特殊的迭代器,创建了一个生成器的对象


obj = create_num(10)
while True:
    try:
        ret = next(obj)
        print(ret)
    except Exception as e:
        print(e.value)
        break
# for i in obj:
#     print(i)

6.生成器send()实现多任务

send和next差不多,但是 通过向send传参数, ret = yield a可以收到参数值

def create_num(all_num):
    print('------1------')
    a, b = 0, 1
    current_num = 0
    while current_num < all_num:
        print('------2------')

        ret = yield a
        print("ret:",ret)
        # print(a)
        print('------3------')
        a, b = b, a + b
        current_num += 1
    return 'ok------ok'
# 如果函数有一个yield语句,这个函数就不是函数了,成为了一个生成器的模板,调用create_num时,生成器是一种特殊的迭代器,创建了一个生成器的对象


obj = create_num(10)
ret = next(obj)
print(ret)
ret = obj.send('wocaowocaowocao')
print(ret)
# for i in obj:
#     print(i)
~                                                                                   
~

7.通过yield完成多任务

看看就能懂

import time


def test1():
    while True:
        print("-----1-----")
        time.sleep(0.1)
        yield


def test2():
    while True:
        print("-----2-----")
        time.sleep(0.1)
        yield


def main():
    t1 = test1()
    t2 = test2()
    while True:
        next(t1)
        next(t2)


if __name__ == "__main__":
    main()
~                                                                                   
~

8.greenlet多任务

调用实例对象后,在两个函数里switch()完成多任务,并发执行

from greenlet import greenlet
import time


def test1():
    while True:
        print("-----1-----")
        gr2.switch()
        time.sleep(0.5)


def test2():
    while True:
        print("-----2-----")
        gr1.switch()
        time.sleep(0.5)


gr1 = greenlet(test1)
gr2 = greenlet(test2)
gr1.switch()

9.gevent完成多任务

这个不常用

import gevent
import time

def f(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        # time.sleep(0.5)
        gevent.sleep(0.5)

# ( 函数名,参数)
g1 = gevent.spawn(f,5)
g2 = gevent.spawn(f,5)
g3 = gevent.spawn(f,5)
# join遇到了延时,等待g1运行完,延时时还能执行其他的
g1.join()
g2.join()
g3.join()

10.gevent多任务-2

这个常用

import gevent
import time
from gevent import monkey


# 打补丁:把当前代码所有耗时的代码换成gevent
monkey.patch_all()

def f(n):
    for i in range(n):
        print(gevent.getcurrent(),i)
        time.sleep(0.5)
        # gevent.sleep(0.5)

# ( 函数名,参数)
# g1 = gevent.spawn(f,5)
# g2 = gevent.spawn(f,5)
# g3 = gevent.spawn(f,5)
# join遇到了延时,等待g1运行完,延时时还能执行其他的
# g1.join()
# g2.join()
# g3.join()

# joinall更常用
gevent.joinall([gevent.spawn(f,5),gevent.spawn(f,5),gevent.spawn(f,5)])

11.案例-图片下载器

看看就懂

import urllib.request
import gevent
from gevent import monkey

monkey.patch_all()

def downloader(img_name, img_url):
    req = urllib.request.urlopen(img_url)

    img_content = req.read()

    with open(img_name, "wb") as f:
        f.write(img_content)


def main():
    gevent.joinall([
            gevent.spawn(downloader, '3.jpg', 'https://rpic.douyucdn.cn/live-cover/roomCover/2022/01/14/39e88aa4a2576eb6f0b64b71aa7730ef_big.png/dy1'),
            gevent.spawn(downloader, '4.jpg', 'http://i2.hdslb.com/bfs/archive/9cbd84d68b1ebe28e39229cbe02ce7f54e8c2365.jpg@672w_378h_1c')
        ])


if __name__ == "__main__":
    main()

三.web服务器v3.1

1.正则表达式简介

直接上案例

1.正则判断变量名是否合理

import re


def main():
    while True:
        name = input("请输入变量名称:(输入quit退出)")
        # match自动判断开头
        # ret = re.match(r"[a-zA-Z_][a-zA-Z_0-9]*$",name)
        ret = re.match(r"^[a-zA-Z_][a-zA-Z_0-9]*$",name)
        if name == 'quit':break
        elif ret:print("成功%s" %ret.group())
        else:print("失败喽!")



if __name__ == "__main__":
    main()

2.正则判断常用邮箱地址

import re


def main():
    while True:
        email_name = input("请输入变量名称:(输入quit退出)")
        # match自动判断开头,\使需要的特殊字符转义

        ret = re.match(r"^[a-zA-Z_0-9]{4,20}@(163|126|qq|gmail)\.com$",email_name)
        if email_name == 'quit':break
        elif ret:print("成功%s" %ret.group())
        else:print("失败喽!")



if __name__ == "__main__":
    main()

2.http

1.实现简单的http服务器

浏览器相当于客户端,向服务器提出请求

服务器回送浏览器需要的数据

import socket


def service_client(new_socket):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    request = new_socket.recv(1024)
    print(request)

    # 返回http格式的数据给浏览器
    # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
    response = "HTTP/1.1 200 OK\r\n"
    response += "\r\n"

    # 准备发送给浏览器的数据 -----body
    response += "<h1>this is a test.</h1>"
    new_socket.send(response.encode("utf-8"))

    #关闭
    new_socket.close()

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 绑定
    tcp_server_socket.bind(("",7890))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    while True:

        # 等待客户链接
        new_socket, client_addr = tcp_server_socket.accept()

        # 服务
        service_client(new_socket)

    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

2.根据客户端需要完成http服务器

import socket


def service_client(new_socket):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    request = new_socket.recv(1024)
    print(request)
    print(">>>>>>>>>>" * 4)    # 返回http格式的数据给浏览器
    # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
    response = "HTTP/1.1 200 OK\r\n"
    response += "\r\n"

    # 准备发送给浏览器的数据 -----body
    # response += "<h1>this is a test.</h1>"
    with open("./html/index.html",'rb') as f:
        f_content = f.read()
    new_socket.send(response.encode("utf-8"))
    new_socket.send(f_content)
    #关闭
    new_socket.close()

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 重复利用同一个端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    # 绑定
    tcp_server_socket.bind(("",7890))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    while True:

        # 等待客户链接
        new_socket, client_addr = tcp_server_socket.accept()

        # 服务
        service_client(new_socket)

    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

3.返回index页面http

import socket
import re


def service_client(new_socket):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    request = new_socket.recv(1024).decode('utf-8')
    # print(request)
    # print(">>>>>>>>>>" * 4)    # 返回http格式的数据给浏览器
    request_lines = request.splitlines()
    print("")
    print(">" * 20)
    print(request_lines)

    file_name = ''
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)
        # print("*" * 50, file_name)
        if file_name == '/':file_name = '/index.html'


    # 准备发送给浏览器的数据 -----body
    # response += "<h1>this is a test.</h1>"
    try:
        with open("./html" + file_name, 'rb') as f:
            f_content = f.read()
    except:
        response = "HTTP/1.1 404 NOT FOUND\r\n"
        response += "\r\n"
        response += "-----file not found-----"
        new_socket.send(response.encode('utf-8'))
    else:
        # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"


        new_socket.send(response.encode("utf-8"))
        new_socket.send(f_content)
    #关闭
    new_socket.close()

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

# 重复利用同一个端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    # 绑定
    tcp_server_socket.bind(("",7890))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    while True:

        # 等待客户链接
        new_socket, client_addr = tcp_server_socket.accept()

        # 服务
        service_client(new_socket)

    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

4.使用多进程完成http服务器

import multiprocessing
import socket
import re


def service_client(new_socket):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    request = new_socket.recv(1024).decode('utf-8')
    # print(request)
    # print(">>>>>>>>>>" * 4)    # 返回http格式的数据给浏览器
    request_lines = request.splitlines()
    print("")
    print(">" * 20)
    print(request_lines)

    file_name = ''
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)
        # print("*" * 50, file_name)
        if file_name == '/':file_name = '/index.html'


    # 准备发送给浏览器的数据 -----body
    # response += "<h1>this is a test.</h1>"
    try:
        with open("./html" + file_name, 'rb') as f:
            f_content = f.read()
    except:
        response = "HTTP/1.1 404 NOT FOUND\r\n"
        response += "\r\n"
        response += "-----file not found-----"
        new_socket.send(response.encode('utf-8'))
    else:
        # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"


        new_socket.send(response.encode("utf-8"))
        new_socket.send(f_content)
    #关闭
    new_socket.close()

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 重复利用同一个端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    # 绑定
    tcp_server_socket.bind(("",7777))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    while True:

        # 等待客户链接
        new_socket, client_addr = tcp_server_socket.accept()

        # 服务
        p = multiprocessing.Process(target = service_client, args = (new_socket,))
        p.start()
        new_socket.close()

    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

5.使用多线程完成http

import threading
import socket
import re


def service_client(new_socket):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    request = new_socket.recv(1024).decode('utf-8')
    # print(request)
    # print(">>>>>>>>>>" * 4)    # 返回http格式的数据给浏览器
    request_lines = request.splitlines()
    print("")
    print(">" * 20)
    print(request_lines)

    file_name = ''
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)
        # print("*" * 50, file_name)
        if file_name == '/':file_name = '/index.html'


    # 准备发送给浏览器的数据 -----body
    # response += "<h1>this is a test.</h1>"
    try:
        with open("./html" + file_name, 'rb') as f:
            f_content = f.read()
    except:
        response = "HTTP/1.1 404 NOT FOUND\r\n"
        response += "\r\n"
        response += "-----file not found-----"
        new_socket.send(response.encode('utf-8'))
    else:
        # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"


        new_socket.send(response.encode("utf-8"))
        new_socket.send(f_content)
    #关闭
    new_socket.close()


def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 重复利用同一个端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    # 绑定
    tcp_server_socket.bind(("",7777))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    while True:

        # 等待客户链接
        new_socket, client_addr = tcp_server_socket.accept()

        # 服务
        t = threading.Thread(target = service_client, args = (new_socket,))
        t.start()

        # 多线程不需要所有的套接字都关闭
        # new_socket.close()

    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

6.协程完成http服务器

import gevent
from gevent import monkey
import socket
import re


monkey.patch_all()


def service_client(new_socket):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    request = new_socket.recv(1024).decode('utf-8')
    # print(request)
    # print(">>>>>>>>>>" * 4)    # 返回http格式的数据给浏览器
    request_lines = request.splitlines()
    print("")
    print(">" * 20)
    print(request_lines)

    file_name = ''
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)
        # print("*" * 50, file_name)
        if file_name == '/':file_name = '/index.html'


    # 准备发送给浏览器的数据 -----body
    # response += "<h1>this is a test.</h1>"
    try:
        with open("./html" + file_name, 'rb') as f:
            f_content = f.read()
    except:
        response = "HTTP/1.1 404 NOT FOUND\r\n"
        response += "\r\n"
        response += "-----file not found-----"
        new_socket.send(response.encode('utf-8'))
    else:
        # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
        response = "HTTP/1.1 200 OK\r\n"
        response += "\r\n"


        new_socket.send(response.encode("utf-8"))
        new_socket.send(f_content)
    #关闭
    new_socket.close()

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 重复利用同一个端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    # 绑定
    tcp_server_socket.bind(("",7777))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    while True:

        # 等待客户链接
        new_socket, client_addr = tcp_server_socket.accept()

        # 服务
        gevent.spawn(service_client, new_socket)


    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

7.单进程单线程非堵塞并发完成http服务器

import socket


def service_client(new_socket):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    request = new_socket.recv(1024)
    print(request)
    print(">>>>>>>>>>" * 4)    # 返回http格式的数据给浏览器
    # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
    response = "HTTP/1.1 200 OK\r\n"
    response += "\r\n"

    # 准备发送给浏览器的数据 -----body
    # response += "<h1>this is a test.</h1>"
    with open("./html/index.html",'rb') as f:
        f_content = f.read()
    new_socket.send(response.encode("utf-8"))
    new_socket.send(f_content)
    #关闭
    new_socket.close()


def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 重复利用同一个端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    # 绑定
    tcp_server_socket.bind(("",7890))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    # 设置套接字为非堵塞的方式
    tcp_server_socket.setblocking(False)

    # 创建一个套接字列表
    new_socket_list = list()
    while True:
        try:
            # 等待客户链接
            new_socket, client_addr = tcp_server_socket.accept()
        except Exception as ret:
            print("-----没有客户端到来-----")
        else:
            print("---客户端到来---")
            new_socket.setblocking(False)
            new_socket_list.append(new_socket)
        for new_socket in new_socket_list:
            try:
                recv_data = new_socket.recv(1024)
            except Exception as ret:
                print("客户端没有发送数据")
            else:
                if recv_data:
                    # 对方发送了数据
                    print("接收到数据")
                else:
                    # 对方调用了close()
                    new_socket_list.remove(new_socket)
                    new_socket.close()





        # 服务
        # service_client(new_socket)

    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

8.单进程单线程非堵塞长连接

import socket
import re

def service_client(new_socket, request):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    # request = new_socket.recv(1024)
    # print(request)
    # print(">>>>>>>>>>" * 4)    # 返回http格式的数据给浏览器
    # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
    request_lines = request.splitlines()
    print('')
    print(">" * 20)
    print(request_lines)

    file_name = ''
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)
        if file_name == '/':
            file_name = '/index.html'
    # 准备发送给浏览器的数据 -----body
    # response += "<h1>this is a test.</h1>"
    try:
        f = open("./html" + file_name, 'rb')
    except:
        response_body = "sorry,there are no file that you wanna."
        response_header = "HTTP/1.1 404 NOT FOUND\r\n"
        response_header += f'Content-Length:{len(response_body)}'
        response_header += '\r\n'
        response = response_header + response_body
        new_socket.send(response.encode('utf-8'))
    else:
        f_content = f.read()
        f.close()
        response_body = f_content
        response_header = "HTTP/1.1 200 OK\r\n"
        response_header += 'Content-Length:%d\r\n' % len(response_body)
        response_header += '\r\n'
        response = response_header.encode('utf-8') + response_body
        new_socket.send(response)


    # 关闭
    # new_socket.close()

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 重复利用同一个端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    # 绑定
    tcp_server_socket.bind(("",7890))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    # 非堵塞
    tcp_server_socket.setblocking(False)

    new_socket_list = list()
    while True:
        try:
            # 等待客户链接
            new_socket, client_addr = tcp_server_socket.accept()
        except Exception as ret:
            pass
        else:
            new_socket.setblocking(False)
            new_socket_list.append(new_socket)

        for client_socket in new_socket_list:
            try:
                recv_data = client_socket.recv(1024).decode('utf-8')
            except Exception as ret:
                pass
            else:
                if recv_data:
                    service_client(client_socket, recv_data)
                else:
                    client_socket.close()
                    new_socket_list.remove(client_socket)

        # 服务
        # service_client(new_socket)

    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()

9.epoll实现http服务器

import socket
import select
import re

def service_client(new_socket, request):
    '''为这个客户端返回数据'''
    # 接受浏览器发送的请求(http请求)
    # request = new_socket.recv(1024)
    # print(request)
    # print(">>>>>>>>>>" * 4)    # 返回http格式的数据给浏览器
    # 准备发送给浏览器的数据 -----header  \r\n表示浏览器可以识别的换行
    request_lines = request.splitlines()
    print('')
    print(">" * 20)
    print(request_lines)

    file_name = ''
    ret = re.match(r"[^/]+(/[^ ]*)", request_lines[0])
    if ret:
        file_name = ret.group(1)
        if file_name == '/':
            file_name = '/index.html'
    # 准备发送给浏览器的数据 -----body
    # response += "<h1>this is a test.</h1>"
    try:
        f = open("./html" + file_name, 'rb')
    except:
        response_body = "sorry,there are no file that you wanna."
        response_header = "HTTP/1.1 404 NOT FOUND\r\n"
        response_header += f'Content-Length:{len(response_body)}'
        response_header += '\r\n'
        response = response_header + response_body
        new_socket.send(response.encode('utf-8'))
    else:
        f_content = f.read()
        f.close()
        response_body = f_content
        response_header = "HTTP/1.1 200 OK\r\n"
        response_header += 'Content-Length:%d\r\n' % len(response_body)
        response_header += '\r\n'
        response = response_header.encode('utf-8') + response_body
        new_socket.send(response)


    # 关闭
    # new_socket.close()

def main():
    # 创建套接字
    tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)

    # 重复利用同一个端口
    tcp_server_socket.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1)

    # 绑定
    tcp_server_socket.bind(("",7777))

    # 变为监听套接字
    tcp_server_socket.listen(128)

    # 非堵塞
    tcp_server_socket.setblocking(False)

    # 创建一个epoll对象
    epl = select.epoll()

    # 将监听套接字对应的fd注册到epoll中
    epl.register(tcp_server_socket.fileno(), select.EPOLLIN)

    fd_event_dict = dict()
    while True:

        fd_event_list = epl.poll()  # 默认会堵塞,直到 os监测到数据到来 通过事件通知方式 告诉这个程序,此时才会解堵塞
 

        # [(df, event), (套接字对应的文件描述符,描述符到底是什么时间例如调用recv接收等)]
        for fd, event in fd_event_list:
            # 等待新客户端的链接
            if fd == tcp_server_socket.fileno():
                new_socket, client_addr = tcp_server_socket.accept()
                epl.register(new_socket.fileno(), select.EPOLLIN)
                fd_event_dict[new_socket.fileno()] = new_socket
            elif event == select.EPOLLIN:
                # 判断已经链接的客户端是否有数据发送过来
                recv_data = fd_event_dict[fd].recv(1024).decode('utf-8')
                if recv_data:
                    service_client(fd_event_dict[fd], recv_data)
                else:
                    fd_event_dict[fd].close()
                    epl.unregister(fd)
                    del fd_event_dict[fd]

        # 服务
        # service_client(new_socket)

    # 关闭
    tcp_server_socket.close()

if __name__ == "__main__":
    main()