在Flask应用中应在何处实例化spaCy等内存密集型对象?
Great question—dealing with heavy, slow-loading libraries like spaCy in Flask is such a common gotcha, and getting this right saves you from massive overhead and glacial request times. Since spaCy is thread-safe and takes ~15 seconds to load, you want to instantiate it once per process, not per request. Here's exactly where and how to do it:
1. For Local Development (Using app.run())
If you're running your app directly with Flask's built-in dev server, load the spaCy model after initializing your Flask app, but before starting the server. This ensures the model is loaded once when the process starts, and all request threads share the same instance.
Example code:
from flask import Flask import spacy # Initialize your Flask app first app = Flask(__name__) # Load spaCy HERE—runs once when the process starts nlp = spacy.load("en_core_web_sm") @app.route("/analyze-text") def analyze_text(): # Use the pre-loaded `nlp` instance in your request handler doc = nlp("Your text to process here") return {"tokens": [token.text for token in doc]} if __name__ == "__main__": # Start the server after loading the model app.run(debug=True)
2. For Production WSGI Servers (Gunicorn, uWSGI)
When deploying with multi-worker WSGI servers, you need to make sure each worker process loads its own spaCy instance (since processes don't share memory). The cleanest way is to load the model when creating your app instance (especially if using an app factory pattern), which ensures each worker gets its own copy when it starts up.
Example with an app factory (common in flaskr-style apps):
# app/__init__.py from flask import Flask import spacy def create_app(): app = Flask(__name__) # Load spaCy inside the app factory—each worker runs this once on startup app.nlp = spacy.load("en_core_web_sm") # Register routes, config, etc. from .routes import bp app.register_blueprint(bp) return app
Then in your run script:
# run.py from app import create_app app = create_app() if __name__ == "__main__": app.run()
When you start Gunicorn with gunicorn --workers=4 run:app, each of the 4 workers will call create_app() independently, loading spaCy once per worker—perfect for thread-safe, efficient usage.
What to Avoid
- Never load spaCy inside a request handler: This would re-load the 15-second model on every single request, killing performance and eating up memory with duplicate instances.
- Don't load the model in the main process before forking workers: If you load spaCy in the main process and then fork workers, each worker will duplicate the model in memory, leading to unnecessary bloat. Always let workers load their own instances.
Key Notes
- spaCy v2.0+ is officially thread-safe, so sharing the instance across request threads in a single process is totally safe.
- Each worker process needs its own spaCy instance (since processes can't share memory), but this is normal and efficient—each worker handles its own set of threads without conflicts.
Hope this helps you optimize your Flask app!
内容的提问来源于stack exchange,提问作者Beowulfenator

