I have been dealing with a really frustrating problem today. Yesterday my code was working and today it was failed without any code changes.
This is the piece of code causing the problem.
app = Flask(__name__, instance_relative_config=True)
app.config.from_object('config')
app.config.from_pyfile('config.cfg')
And this is the error.
Traceback (most recent call last):
File "run.py", line 1, in
from project import app
File "C:\Python27\env\vod_test\src\project\__init__.py", line 37, in
load_config()
File "C:\Python27\env\vod_test\src\project\__init__.py", line 33, in load_config
app.config.from_pyfile('config.cfg')
File "C:\Python27\env\vod_test\lib\site-packages\flask\config.py", line 129, in from_pyfile
with open(filename) as config_file:
IOError: [Errno 2] Unable to load configuration file (No such file or directory): 'C:\\Python27\\env\\vod_test\\var\\project-instance\\config.cfg'
Flask is trying to load the config file from C:\\Python27\\env\\vod_test\\var\\project-instance\\config.cfg
instead of from C:\\Python27\\env\\vod_test\\project\\instance\\config.cfg
. Where is the var
coming from? And why is there a hyphen between project
and instance
?
The strange thing was that the problem only occurred when I was running my test cases from the command line. In PyCharm the code was working. How frustrating. It turned out that PyCharm was using a different virtualenv than the command line. After comparing the output of ‘pip freeze’ I discovered that some libraries had different versions.
To solve the problem I added the following code.
import os
from flask import Flask
def load_instance_config_fix(filename):
config = {}
with app.open_instance_resource(filename) as f:
for line in f:
if line[0] == "#":
continue
name, value = line.partition("=")[::2]
config[name.strip()] = value.strip()
return config
def handle_incorrect_instance_path(f):
def handle_load_instance_config():
try:
f()
except IOError:
app.instance_path = os.path.join(os.path.abspath(os.curdir), 'instance')
config = load_instance_config_fix('config.cfg')
app.config.update(config)
return handle_load_instance_config
@handle_incorrect_instance_path
def load_config():
app.config.from_object('config')
app.config.from_pyfile('config.cfg')
app = Flask(__name__, instance_relative_config=True)
load_config()
@app.route('/')
def hello_world():
return 'Hello, World!'
Just some nice syntactic sugar with a decorator to keep the code nice and concise.
Another way to solve the problem is by setting the instance_path when initializing Flask. What fun would that be 🙂
import os
from flask import Flask
app = Flask(__name__, instance_path=os.path.join(os.path.abspath(os.curdir), 'instance'), instance_relative_config=True)
app.config.from_object('config')
app.config.from_pyfile('config.cfg')
@app.route('/')
def hello_world():
return 'Hello, World!'
Back to real coding 🙂