8wDlpd.png
8wDFp9.png
8wDEOx.png
8wDMfH.png
8wDKte.png

Flask - 对象仅在请求上下文中发生更改

Tasos Papastylianou 2月前

18 0

我在一个大型多线程 Flask 应用程序中遇到了一个奇怪的问题,我设法用大约十几行代码重现了这个问题。似乎每当我修改内部对象的属性时...

我在一个大型多线程 Flask 应用程序中遇到了一个奇怪的问题,我设法用大约十几行代码重现了这个问题。似乎每当我修改与 Flask 中的路由绑定的函数内对象的属性时,该属性只会在该路由函数的上下文中被修改,而在任何路由函数之外,它都保留其先前的值。作为示例,我在这里使用 __init__.py 和 routes.py 函数在 /app/ 目录中定义了一个 \'app\' 包。

应用程序/__init__.py:

from flask import Flask

class NumberStore:
    def __init__(self):
        self.number = 1

    def set_number(self, number):
        self.number = number

app = Flask(__name__)
numberstore = NumberStore()

from app import routes

应用程序/routes.py:

from app import app, numberstore

@app.route('/get')
def get():
    return f"The number holder has id {id(numberstore)} and the number is {numberstore.number}"

@app.route('/set')
def set():
    numberstore.set_number(2)
    return f"The number holder has id {id(numberstore)} and the number has been set to {numberstore.number}"

此外,我还有一个便捷脚本,可以在线程中运行服务器:

运行服务.py:

import requests
from multiprocessing import Process

from app import app, numberstore

s = Process(target=lambda : app.run())
s.start()

当我在交互式会话中启动服务器并点击 \'/set\' 端点时,我期望 的值 numberstore.number 更改为 2,并且确实如此 - 对于 \'/get\' 和 \'/set\' 端点。但是,当我在路由函数上下文之外访问对象时, 的值 numberstore.number 仍为 1。同样,如果我在交互式会话中手动调用该 set_number 方法,则更改不会传播到路由函数。尽管对象 ID 在所有情况下都保持不变,但这一切都会发生。由于 ID 指的是对象在内存中的实际位置,这对我来说似乎是不可能的。

laptop:~/testserver$ python3 -i runserv.py 
 * Serving Flask app 'app'
 * Debug mode: off
>>> WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://127.0.0.1:5000
Press CTRL+C to quit

>>> numberstore.number
1
>>> id(numberstore)
139855264957008
>>> print(requests.get("http://127.0.0.1:5000/get").text)
The number holder has id 139855264957008 and the number is 1
>>> print(requests.get("http://127.0.0.1:5000/set").text)
The number holder has id 139855264957008 and the number has been set to 2
>>> numberstore.number
1
>>> print(requests.get("http://127.0.0.1:5000/get").text)
The number holder has id 139855264957008 and the number is 2
>>> numberstore.set_number(3)
>>> numberstore.number
3
>>> print(requests.get("http://127.0.0.1:5000/get").text)
The number holder has id 139855264957008 and the number is 2

在我看来,这是一个功能,而不是一个错误,我假设它与 Flask 为每个请求启动的请求会话有关。我的问题是 - Flask 为什么这样做,是否有可能绕过它?我的真实服务器中采取的几乎所有操作都是由数据库更改组成的,这显然没有这个问题。但是,有一个实例,我确实需要从路由的 Flask 端点函数中修改模块级对象的属性。可以这样做吗?

帖子版权声明 1、本帖标题:Flask - 对象仅在请求上下文中发生更改
    本站网址:http://xjnalaquan.com/
2、本网站的资源部分来源于网络,如有侵权,请联系站长进行删除处理。
3、会员发帖仅代表会员个人观点,并不代表本站赞同其观点和对其真实性负责。
4、本站一律禁止以任何方式发布或转载任何违法的相关信息,访客发现请向站长举报
5、站长邮箱:yeweds@126.com 除非注明,本帖由Tasos Papastylianou在本站《python》版块原创发布, 转载请注明出处!
最新回复 (0)
  • 搞清楚了——Flask 派生了另一个进程来路由端点,但我没有发现。我没有意识到即使在两个独立的地址空间内,对象 ID 也会保持不变。

     python3 -i runserv.py 
     * Serving Flask app 'app'
     * Debug mode: off
    >>> WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
     * Running on http://127.0.0.1:5000
    Press CTRL+C to quit
    
    >>> print(requests.get("http://127.0.0.1:5000/get").text)
    127.0.0.1 - - [29/Aug/2024 17:18:57] "GET /get HTTP/1.1" 200 -
    The number holder has id 139782623142480, the process id is 69246, and the number is 1
    >>> import os
    >>> os.getpid()
    69244
    
    
返回
作者最近主题: