Reputation: 1436
I'm used to object oriented programming, dependency injection, etc. That said, I'm having trouble dealing with flask, and moving some objects around that need near global access. I have my routes segregated to a file called WebServer.py
. I have a Main.py
which serves as the entry point for the application.
Main.py:
x = "test"
import WebServer
# WSGI entry point
def main():
return WebServer.app
if __name__ == '__main__':
from DebugWebServer import DebugWebServer
server = DebugWebServer()
server.run(WebServer.app)
WebServer.py:
from flask import Flask
from flask import render_template
from flask import Response
app = Flask(__name__)
@app.route('/')
def index():
global x
print(x)
return render_template('index.html')
x
is not accessible in the index route, even if I note that it's global.
I have little experience with global variables, but I thought this would work. Does anyone know how I can make objects instantiated in Main.py
accessible to WebServer.py
?
Upvotes: 0
Views: 580
Reputation: 71454
Circular dependencies are bad. Your main
should pass x
as a parameter to your WebServer
code rather than having WebServer
import main
to get it for itself.
(edit) I'm not familiar with Flask best practices specifically, but just looking at the code and thinking about how to apply dependency injection to it, it seems like something like this should work:
main.py:
from flask import Flask
from webserver import get_app
x = "test"
# WSGI entry point
def main() -> Flask:
return get_app(x)
if __name__ == '__main__':
from DebugWebServer import DebugWebServer
server = DebugWebServer()
server.run(main())
webserver.py:
from flask import Flask, render_template, Response
def get_app(x: str) -> Flask:
app = Flask(__name__)
@app.route('/')
def index():
print(x)
return render_template('index.html')
return app
Upvotes: 4
Reputation: 5202
You want to import the x
variable from the Main
module.
from Main import x
Upvotes: 1
Reputation: 77892
Python's notion of "global" really means "module level" - there's NO process-wide global namespace, and the goal of the global
keyword is only to allow rebinding of module-level variables from within a function (which is still considered bad practice unless there's really no other solution, which is rarely the case).
Also, you should particularily not use globals (I mean mutable globals) in a wsgi app - those apps are typically served (on production) as long-running processes in a multi-process pool, and any of the processes (usually the first inactive one) will serve a given request, so your mutable global state 1/ will affect all requets served by this process and 2/ will not be shared between different processes. So if you want to share state between processes, you use either sessions (for volatile data) or a proper database (for peristant data).
wrt/ globals, as a general rule, you can usually avoid them with plain simple well known programming features: functions arguments, functions return values, and (if you have state to share between function calls that are not directly adjacents) classes.
Now if your variable is some readonly configuration variable (which is ok - there's no issue with this), the proper solution in your case here is to create a distinct config module and import it where needed, ie
config.py:
# naming convention: use ALL_UPPER for pseudo-constants
X = 42
webserver.py
from flask import Flask
from flask import render_template
from flask import Response
import config
app = Flask(__name__)
@app.route('/')
def index():
print(config.X)
return render_template('index.html')
main.py
# note that this is your module, not the WebServer.WebServer class
# following naming conventions (module names should be all_lower)
# helps avoiding this kind of confusions
import WebServer
# contrived example, just to find a use for `config.X` here
import config
print("in main, config.X = {}".format(config.X)
# WSGI entry point
def main():
return WebServer.app
if __name__ == '__main__':
from DebugWebServer import DebugWebServer
server = DebugWebServer()
server.run(WebServer.app)
Upvotes: 3