Python/Tornado Class 包装缓存问题
Python/Tornado Class wrapper caching issue
我正在围绕 Python 的数组数据结构实现一个包装器。我在我的应用程序中出于实际原因这样做,但提供此示例代码只是为了重现该问题。对于通过 Tornado 抽象的每个请求,该数组似乎并不是 'cleared'。
如果我不使用我的数组抽象,就没有问题。这让我相信 CPython 实现中某处存在错误。
from tornado import websocket, web, ioloop
import json
class Array():
_data = []
def push(self, value):
self._data.append(value)
def json(self):
return json.dumps(self._data)
class ClientHandler(web.RequestHandler):
def prepare(self):
self.set_header("content-type", "application/json")
def get(self):
array = Array()
for i in range(0, 6):
array.push({'id': i})
self.write(array.json())
self.finish()
app = web.Application([
(r'/client', ClientHandler),
], debug=True)
if __name__ == '__main__':
kwargs = {"address": "127.0.0.1"}
app.listen(port=8888, **kwargs)
ioloop.IOLoop.instance().start()
启动 python 进程后刷新页面后得到的输出顺序如下:
序列 1
[{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}]
序列 2
[{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}, {"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}]
序列 3
[{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}, {"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}, {"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}]
此响应输出不是预期输出。预期输出的长度应为 JSON 输出数组的 6。如果我不包装 Python 的数据结构,这个问题就不会发生。
为什么会这样?我是一个热心的 Python 新用户,但是如果这种语言甚至不能处理简单的抽象,这种类型的事情会阻止我使用它。
额外
给运行这个:
- 在
pip install tornado
、 安装 Tornado 包
- 将我提供的代码保存在名为
app.py
的文件中
- 执行
python app.py
- 在您的浏览器中打开
http://127.0.0.1/client
的 Web 应用程序
问题是因为 Array._data
实际上是 Array
的静态成员,这意味着它的值在 Array
.
的所有实例中都是相同的
class Array():
_data = []
def push(self, value):
self._data.append(value)
def json(self):
return json.dumps(self._data)
要解决此问题,请将 _data
设为实例成员。
class Array():
def __init__(self):
self._data = []
def push(self, value):
self._data.append(value)
def json(self):
return json.dumps(self._data)
我正在围绕 Python 的数组数据结构实现一个包装器。我在我的应用程序中出于实际原因这样做,但提供此示例代码只是为了重现该问题。对于通过 Tornado 抽象的每个请求,该数组似乎并不是 'cleared'。
如果我不使用我的数组抽象,就没有问题。这让我相信 CPython 实现中某处存在错误。
from tornado import websocket, web, ioloop
import json
class Array():
_data = []
def push(self, value):
self._data.append(value)
def json(self):
return json.dumps(self._data)
class ClientHandler(web.RequestHandler):
def prepare(self):
self.set_header("content-type", "application/json")
def get(self):
array = Array()
for i in range(0, 6):
array.push({'id': i})
self.write(array.json())
self.finish()
app = web.Application([
(r'/client', ClientHandler),
], debug=True)
if __name__ == '__main__':
kwargs = {"address": "127.0.0.1"}
app.listen(port=8888, **kwargs)
ioloop.IOLoop.instance().start()
启动 python 进程后刷新页面后得到的输出顺序如下:
序列 1
[{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}]
序列 2
[{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}, {"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}]
序列 3
[{"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}, {"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}, {"id": 0}, {"id": 1}, {"id": 2}, {"id": 3}, {"id": 4}, {"id": 5}, {"id": 6}]
此响应输出不是预期输出。预期输出的长度应为 JSON 输出数组的 6。如果我不包装 Python 的数据结构,这个问题就不会发生。
为什么会这样?我是一个热心的 Python 新用户,但是如果这种语言甚至不能处理简单的抽象,这种类型的事情会阻止我使用它。
额外
给运行这个:
- 在
pip install tornado
、 安装 Tornado 包
- 将我提供的代码保存在名为
app.py
的文件中
- 执行
python app.py
- 在您的浏览器中打开
http://127.0.0.1/client
的 Web 应用程序
问题是因为 Array._data
实际上是 Array
的静态成员,这意味着它的值在 Array
.
class Array():
_data = []
def push(self, value):
self._data.append(value)
def json(self):
return json.dumps(self._data)
要解决此问题,请将 _data
设为实例成员。
class Array():
def __init__(self):
self._data = []
def push(self, value):
self._data.append(value)
def json(self):
return json.dumps(self._data)