Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
733 views
in Technique[技术] by (71.8m points)

python - Increment counter for every access to a Flask view

I want to increment a counter when users access a page in my Flask app. If two users access the page, the count should increase by 2. I tried the following but the count is always 1. How do I increment the value for each access?

@app.route('/count')
def make_count():
    count = 0
    value = count + 1
    return jsonify(count=value)
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

Counting concurrently is hard. Assume the count is 0. If two users both hit the endpoint at close enough intervals, they may each get the value 0, increment it to 1, and put it back. Two users hit the endpoint, but the resulting count is 1, not 2. To get around this, you need to use a data store that supports incrementing atomically (as in, an operation that only one process can do at a time).

You can't use a simple Python global because WSGI servers will spawn multiple processes, so they will each have their own independent copy of the global. Repeated requests could be handled by different processes, resulting in different, unsynchronized values.

The simplest solution is a Python multiprocessing.Value. This synchronizes access to a shared value across processes, as long as the processes are spawned after the value is created.

from flask import Flask, jsonify
from multiprocessing import Value

counter = Value('i', 0)
app = Flask(__name__)

@app.route('/')
def index():
    with counter.get_lock():
        counter.value += 1
        out = counter.value

    return jsonify(count=out)

app.run(processes=8)
# access http://localhost:5000/ multiple times quickly, the count will be correct

There are still some caveats:

  • The data only persists as long as the manager is alive. If you restart the server, the counter resets too.
  • If the application processes are distributed across multiple machines, shared memory suffers the same issues as globals: they are only synchronized on the local machine, not across the network.

For real world scenarios, Redis is a much more robust solution. The server is independent of the web application, has options for persistence, and can do atomic increments. It can also be used for other parts of the application, such as caching.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...