You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python3.9环境下Django第三方库类型提示错误的补丁方案咨询

解决Python 3.9下rest_framework_simple_api_key的类型提示错误

问题背景

在Python 3.9的生产环境中使用rest_framework_simple_api_key,运行python manage.py generate_fernet_key命令时触发以下错误:

File "C:\Users\DELL\anaconda3\lib\site-packages\rest_framework_simple_api_key\models.py", line 15, in <module>
class AbstractAPIKeyManager(models.Manager):
File "C:\Users\DELL\anaconda3\lib\site-packages\rest_framework_simple_api_key\models.py", line 16, in AbstractAPIKeyManager
def get_api_key(self, pk: int | str):
TypeError: unsupported operand type(s) for |: 'type' and 'type'

错误原因明确:int | str是Python 3.10及以上版本才支持的联合类型语法,Python 3.9无法解析该语法,导致模块导入失败。

补丁方案可行性分析

用猴子补丁解决该问题完全可行,但你之前的补丁实现时机错误:补丁代码是先导入rest_framework_simple_api_key.models模块再修改方法,而模块导入时Python会先解析所有代码,遇到int | str直接触发错误,根本执行不到打补丁的逻辑。必须在模块被加载解析前,修改掉不兼容的语法。

正确解决方法

方法一:运行时修改模块源代码(猴子补丁)

编写补丁代码,在模块加载前替换掉不兼容的类型语法,确保Python 3.9能正常解析模块内容。

  1. 编写monkey_patch.py:
import sys
import os
import importlib.util
from importlib.machinery import SourceFileLoader

def patch_rest_framework_simple_api_key():
    # 定位rest_framework_simple_api_key的安装路径
    if 'rest_framework_simple_api_key' in sys.modules:
        package_path = os.path.dirname(sys.modules['rest_framework_simple_api_key'].__file__)
    else:
        spec = importlib.util.find_spec('rest_framework_simple_api_key')
        package_path = spec.submodule_search_locations[0]
    
    models_file = os.path.join(package_path, 'models.py')
    
    # 读取文件内容并替换不兼容语法
    with open(models_file, 'r', encoding='utf-8') as f:
        content = f.read()
    
    # 添加Union导入语句(如果不存在)
    if 'from typing import Union' not in content:
        content = content.replace(
            'from django.db import models',
            'from typing import Union\nfrom django.db import models'
        )
    
    # 替换int | str为Union[int, str]
    content = content.replace('int | str', 'Union[int, str]')
    
    # 动态加载修改后的模块
    module_name = 'rest_framework_simple_api_key.models'
    if module_name in sys.modules:
        del sys.modules[module_name]
    
    loader = SourceFileLoader(module_name, models_file)
    sys.modules[module_name] = loader.load_module()
    
    print("rest_framework_simple_api_key 已完成补丁,兼容Python 3.9")
  1. 修改manage.py,在最开头执行补丁(确保在任何导入目标模块的代码之前):
import os
import sys

# 优先执行补丁
from roomroot.monkey_patch import patch_rest_framework_simple_api_key
patch_rest_framework_simple_api_key()

def main():
    """Run administrative tasks."""
    settings_module = "roomroot.deployment" if "WEBSITEHOSTNAME" in os.environ else "roomroot.settings"
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", settings_module)
    
    try:
        from django.core.management import execute_from_command_line
    except ImportError as exc:
        raise ImportError(
            "Couldn't import Django. Are you sure it's installed and "
            "available on your PYTHONPATH environment variable? Did you "
            "forget to activate a virtual environment?"
        ) from exc
    execute_from_command_line(sys.argv)

if __name__ == '__main__':
    main()

方法二:降级到兼容Python 3.9的版本

更简单的方案是直接安装rest_framework_simple_api_key的旧版本,选择不使用int | str语法的发布版本,执行以下命令:

pip install rest_framework_simple_api_key==<兼容版本号>

你可以查看该包的版本历史,找到明确支持Python 3.9的版本(例如v1.6.0及之前的版本,具体以官方版本说明为准)。

为什么之前的补丁无效

你在settings.py、apps.py、manage.py中调用补丁的时机太晚:当这些文件执行时,Django已经开始加载第三方应用模块,rest_framework_simple_api_key.models已经被导入并触发语法错误,补丁代码根本没机会执行。必须在任何导入目标模块的代码之前执行补丁逻辑。

内容的提问来源于stack exchange,提问作者Abha Rani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.24 02:45:04