一、Windows上多个版本 Python/pip 和 Uvicorn的共用共存方法
windows上使用多个版本的python,pip以及在对应版本的环境中使用uvicorn需要注意的一些事情,在此做个笔记。
比如我目前电脑上安装了两个版本的python,分别是Python3.8和最新的Python3.11,而python3.11是我最新安装的python版本。
在windows上的git命令窗口中目前使用python -V,显示的是Python3.8.6,而我当前电脑中存在多个python项目,有的项目需要使用原版本3.8,有的则需要使用新版本3.11,显示使用使用python不能达到我的预期目的。
要使用python3.11,可以将其安装目录下的Python.exe在同目录中复制一份且命名为如python311,这里需要注意不要直接将 python.exe 直接重命名为 python311.exe,这样的话使用pip时就会报错:Fatal error in launcher: Unable to create process using '"C:\Python311\python.exe"之类的错误。
此处我没有尝试,但我想在使用pip的时候有没有可能通过设置其要查找的exe文件路径解决,不过当下的方式已经可以满足条件,也无所谓了。
基本我们就可以开始使用python进行pip的安装以及使用uvicorn服务。当然首先要记得将两个python目录和scripts目录写到环境变量里,然后在使用pip的时候使用如下的方式:
#原python版本环境中使用pip查看列表及安装模块
python -m pip list
python -m pip install uvicorn
#3.11版本环境中使用pip查看列表及安装模块
python311 -m pip list
python311 -m pip install uvicorn
安装uvicorn模块之后,默认uvicorn在两个python版本中的scripts文件夹中都是uvicorn.exe,直接使用uvicorn启动命令会默认使用老版本的python及其uvicorn,这时需要将新python版本中scripts目录里的uvicorn更换一下名称,如uvicorn311。
然后就可以通过如下命令来启动两个python环境下的uvicorn项目服务。
#老版本下的python项目
uvicorn main:app --host=127.0.0.1 --port=8000 --reload
#3.11版本中的python项目
uvicorn311 main:app --host=127.0.0.1 --port=8000 --reload
二、uvicorn本地开发fastapi时启用多worker模式
uvicorn在本地启动开发的fastapi程序时,想试试看多worker模式,发现其在启动的时候有一行提示:
$ uvicorn main:app --host=10.118.11.26 --port=8000 --workers=3 --reload
WARNING: "workers" flag is ignored when reloading is enabled.
即当开启了reload 热加载模式时,workers配置将会被忽略。所以在本地开发时如果想体验多worker模式,就不要使用 --reload。这是一个很小的点,但是如果没有注意到这项提示,并且启动后去查看进程发现怎么操作都没有按预期实现多进程时,会很崩溃,因为uvicorn此时并不会因为这样的配置导致无法运行,只是在众多的提示中多了一行字符,很难引起开发者注意,可能导致用户浪费很多的时候去排查。
三、Python3.11版本uvicorn运行报错content = [STATUS_LINE[status_code]]
之前一直运行顺利的一段代码,突然运行的时候出现了报错http\httptools_impl.py..content = [STATUS_LINE[status_code]]。详细报错内容如下:
# 报错内容
await send(message)
File "C:\Python3.11.0\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py", line 499, in send
content = [STATUS_LINE[status_code]]
# 涉及的程序部分
class AppException(Exception):
def __init__(code..., message...)
# 异常部分
raise AppException(code=801, message="格式错误")
排查发现使用raise AppException抛出异常问题的时候,801这个code会导致报错,追踪到程序出错的文件及相关的内容如下:
C:\Python3.11.0\Lib\site-packages\uvicorn\protocols\http\httptools_impl.py STATUS_LINE = { status_code: _get_status_line(status_code) for status_code in range(100, 600) }
对比发现当前我运行的python项目中 uvicorn 的版本为 0.20.0 ,而之前运行成功的 uvicorn 版本为 0.13.4 。并对比了一下两个版本中的 httptools_impl.py 文件,未去寻找最终导致报错的语句逻辑在哪,但经过尝试,可以判定为更新的版本对传入的code参数有要求,必须在100-600之间,而在之前的版本中虽然也有这个范围,但是不会强制要求不会报错。找到了问题点就好办了,可以通过底层修改传入的code, 并且如果有其它需要传递其它的内容,可以在__init__方法中添加其它的参数进行处理。