python利用多线程让http请求异步返回

有时我们可能会碰到这样一种情况,我们有一个功能,这个功能对外提供了一个http接口,我们需要对这个http接口发起请求才能启动这个服务,但是这个服务功能可能会执行很久,这样如果等功能执行结束再返回请求结果,那这个请求可能就超时了,

发起请求的客户端

 import requests
  
 req = requests.get("http://127.0.0.1:9898/register?username=aaa&pwd=232323")
 print(req.content)

服务端

# coding=utf-8
import flask
from flask import jsonify
from flask import request

from gevent import pywsgi

import sys
reload(sys)
import time
sys.setdefaultencoding('utf-8')

server = flask.Flask(__name__)

@server.route('/register', methods=['get', 'post'])
def registerPost():
    # post请求获取请求的参数,返回结果类型是str
    username = request.values.get('username')
    pwd = request.values.get('pwd')
    app_id = request.values.get('app_id')
    dowork(app_id)
    # confirmpwd = request.values.get('confirmpwd')
    if username and pwd:  # 判断输入的用户名、密码、确认密码都不为空
        return ("用户名为:%s, 密码为:%s" % (username, pwd))
    else:
        return jsonify({"code": 504, "msg": "必填项不能为空"})


if __name__ == '__main__':
    # port可以指定端口,默认端口是5000
    # host默认是127.0.0.1,写成0.0.0.0的话,其他人可以访问,代表监听多块网卡上面,
    # server.run(debug=True, port=9898, host='0.0.0.0')
    server = pywsgi.WSGIServer(('0.0.0.0', 9898), server)
    server.serve_forever()

这个就是一个典型的同步返回结果,发起请求后,必须等 dowork() 功能执行完之后才能返回请求结果,如果 dowork() 执行时间较长,则会导致客户端请求超时

这时我们可能就需要一个异步的http接口,收到客户端的请求后,马上返回一个请求结果,然后再慢慢的执行要执行的任务,这个过程怎么实现呢,我的做法是通过多线程来实现,在服务端的响应函数中,每次收到一个请求,获取请求中携带的参数,然后用这些参数创建一个会执行我们功能服务的线程,最后返回请求结果,这样客户端可以很快获取到请求结果,从而不会让客户端请求超时

下面是加入了线程的服务端的响应函数

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import flask
from flask import jsonify
from flask import request

from gevent import pywsgi

import sys
reload(sys)
import time
sys.setdefaultencoding('utf-8')

server = flask.Flask(__name__)

import threading
import time

exitFlag = 0

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter, app_id):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
        self.app_id = app_id
    def run(self):
        print ("开始线程:" + self.name)
        print_time(self.name, self.counter, 1, self.app_id)
        print ("退出线程:" + self.name)

def print_time(threadName, delay, counter, app_id):
    while counter:
        if exitFlag:
            threadName.exit()
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        dowork(app_id)
        counter -= 1

@server.route('/register', methods=['get', 'post'])
def registerPost():
    # post请求获取请求的参数,返回结果类型是str
    username = request.values.get('username')
    pwd = request.values.get('pwd')
    app_id = request.values.get('app_id')

    # 创建新线程
    thread1 = myThread(1, "Thread-1", 1, app_id)
    # 开启新线程
    thread1.start()

    # confirmpwd = request.values.get('confirmpwd')
    if username and pwd:  # 判断输入的用户名、密码、确认密码都不为空
        return ("用户名为:%s, 密码为:%s" % (username, pwd))
    else:
        return jsonify({"code": 504, "msg": "必填项不能为空"})


if __name__ == '__main__':
    # port可以指定端口,默认端口是5000
    # host默认是127.0.0.1,写成0.0.0.0的话,其他人可以访问,代表监听多块网卡上面,
    # server.run(debug=True, port=9898, host='0.0.0.0')
    server = pywsgi.WSGIServer(('0.0.0.0', 9898), server)
    server.serve_forever()

因为线程的run()方法和start()方法是不能传递参数的,所以如果我们需要从请求中获取参数然后传递给要执行的功能的话,可以在线程的构造方法的参数中加上我们需要传递的参数,这样在run()方法内部我们就能动态获得请求中传递的参数了

下面是菜鸟教程里面的多线程模板

'''
遇到问题没人解答?小编创建了一个Python学习交流QQ群:778463939
寻找有志同道合的小伙伴,互帮互助,群里还有不错的视频学习教程和PDF电子书!
'''
import threading
import time

class myThread (threading.Thread):
    def __init__(self, threadID, name, counter):
        threading.Thread.__init__(self)
        self.threadID = threadID
        self.name = name
        self.counter = counter
    def run(self):
        print ("开启线程: " + self.name)
        # 获取锁,用于线程同步
        threadLock.acquire()
        print_time(self.name, self.counter, 3)
        # 释放锁,开启下一个线程
        threadLock.release()

def print_time(threadName, delay, counter):
    while counter:
        time.sleep(delay)
        print ("%s: %s" % (threadName, time.ctime(time.time())))
        counter -= 1

threadLock = threading.Lock()
threads = []

# 创建新线程
thread1 = myThread(1, "Thread-1", 1)
thread2 = myThread(2, "Thread-2", 2)

# 开启新线程
thread1.start()
thread2.start()

# 添加线程到线程列表
threads.append(thread1)
threads.append(thread2)

# 等待所有线程完成
for t in threads:
    t.join()
print ("退出主线程")

执行以上程序,输出结果为:

开启线程: Thread-1
开启线程: Thread-2
Thread-1: Wed Apr  6 11:52:57 2016
Thread-1: Wed Apr  6 11:52:58 2016
Thread-1: Wed Apr  6 11:52:59 2016
Thread-2: Wed Apr  6 11:53:01 2016
Thread-2: Wed Apr  6 11:53:03 2016
Thread-2: Wed Apr  6 11:53:05 2016
  • 6
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当然,下面是一个关于 Python 异步多线程的简单例子: ``` import asyncio async def my_function(id): print(f"Started {id}") await asyncio.sleep(1) print(f"Finished {id}") async def main(): tasks = [] for i in range(10): tasks.append(asyncio.create_task(my_function(i))) await asyncio.gather(*tasks) await main() ``` 这个例子中,我们使用了 `asyncio` 库来创建协程。我们定义了一个函数 `my_function`,它会打印一条消息,然后使用 `asyncio.sleep` 函数来暂停一秒钟。我们还定义了一个主函数 `main`,它会创建十个任务并将它们放在一个列表中。然后使用 `asyncio.gather` 函数来并发地执行所有任务。 这是一个简单的例子,但它展示了 Python 异步多线程的基本用法。 ### 回答2: Python异步多线程是指在处理多个任务时,能够实现任务的并发执行,提高程序的效率。 以下是一个使用Python异步多线程的例子: ```python import asyncio import aiohttp async def fetch(session, url): async with session.get(url) as response: return await response.text() async def main(): urls = ['http://www.example.com', 'http://www.google.com', 'http://www.python.org'] async with aiohttp.ClientSession() as session: # 创建一个异步任务列表 tasks = [fetch(session, url) for url in urls] # 并发执行异步任务 responses = await asyncio.gather(*tasks) # 处理响应结果 for response in responses: print(response) # 运行异步任务 asyncio.run(main()) ``` 在上述例子中,我们使用了asyncio库和aiohttp库实现了异步多线程。main()函数是一个异步函数,通过创建一个异步任务列表(tasks),然后使用`asyncio.gather(*tasks)`并发执行这些任务。我们使用aiohttp库发送HTTP请求,fetch函数是一个异步函数,在session.get(url)时会进行协程切换,从而实现并发执行多个网络请求。 当所有异步任务执行完毕后,我们就可以处理响应结果。 这个简单的例子展示了Python异步多线程的使用,它可以在处理IO密集型任务时提高程序的效率,避免了阻塞等待的问题。通过使用异步多线程,我们可以实现高效的并发编程。 ### 回答3: Python异步多线程是指多个线程可以同时运行,并且线程之间可以并行执行不同的任务。下面是一个简单的Python异步多线程的例子: ``` import asyncio import time import threading # 异步函数,用于模拟耗时操作 async def async_operation(): print("开始异步操作") await asyncio.sleep(2) print("异步操作完成") # 多线程函数 def thread_function(): print("开始线程操作") time.sleep(2) print("线程操作完成") # 创建事件循环对象 loop = asyncio.get_event_loop() # 创建异步任务 async_task = asyncio.ensure_future(async_operation()) # 创建多线程任务 thread = threading.Thread(target=thread_function) # 开启线程 thread.start() # 在事件循环中运行异步任务 loop.run_until_complete(async_task) # 等待线程结束 thread.join() # 关闭事件循环 loop.close() ``` 在这个例子中,我们使用`asyncio`和`threading`模块来实现异步多线程操作。其中,`async_operation`函数是一个异步函数,通过`await asyncio.sleep(2)`来模拟一个耗时操作。`thread_function`函数是一个普通的多线程函数,通过`time.sleep(2)`来模拟一个耗时操作。 我们首先创建一个事件循环对象`loop`,然后使用`asyncio.ensure_future`创建一个异步任务`async_task`,使用`threading.Thread`创建一个多线程任务`thread`。接着,通过`thread.start()`开启线程,通过`loop.run_until_complete`在事件循环中运行异步任务。 最后,使用`thread.join()`等待线程结束,`loop.close()`关闭事件循环。通过这段代码,我们可以同时运行异步任务和多线程任务,并且在主线程中等待它们完成。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值