0

I tried few solved questions on stackoverflow but couldn't make it work. Can someone kindly help me to fix this. I am using Flask for one of my project and this is the error I am getting. Following is the code and traceback.

The code is related to line 12 in sqlutils.py.

import hashlib
import os
import oursql
import uuid
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from mainapp import app

app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+oursql://'+os.environ.get('DB_USR') \
                                        + ':' + os.environ.get('DB_PASSWD')+'@'\
                                        + os.environ.get('DB_HOST') + '/school_new'
db = SQLAlchemy(app)

Traceback:

Traceback (most recent call last):
  File "run.py", line 3, in <module>
    from mainapp import app
  File "/home/osboxes/school/mainapp-web/mainapp/__init__.py", line 85, in <module>
    import views
  File "/home/osboxes/school/mainapp-web/mainapp/views.py", line 8, in <module>
    from mainapp.students.availability_students import add_availability, delete_availability, get_availabilities_by_username, \
  File "/home/osboxes/school/mainapp-web/mainapp/students/availability_students.py", line 3, in <module>
    from .sqlutils import build_where, build_set, get_connection
  File "/home/osboxes/school/mainapp-web/mainapp/students/sqlutils.py", line 12, in <module>
    + os.environ.get('DB_HOST') + '/school_new'
TypeError: cannot concatenate 'str' and 'NoneType' objects
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
Shazia Nusrat
  • 174
  • 1
  • 10
  • 36

4 Answers4

2

You need to provide some sensible defaults for when the environment doesn't contain your settings:

DB_HOST = os.environ.get('DB_HOST', 'localhost')
DB_USR = os.envrion.get('DB_USR', 'root')
DB_PASSWD = os.environ.get('DB_PASSWD', 'sekret')

DB_URL = 'mysql+oursql://{}:{}@{}/school_new'

app.config['SQLALCHEMY_DATABASE_URI'] = DB_URL.format(DB_USR, DB_PASSWD, DB_HOST)

Or raise an error if critical settings are not provided:

DB_HOST = os.environ.get('DB_HOST')
DB_USR = os.environ.get('DB_USR')
DB_PASSWD = os.environ.get('DB_PASSWD')

if not all([DB_HOST, DB_USR, DB_PASSWD]):
   raise Exception('Missing Database Environment Variables')
Burhan Khalid
  • 169,990
  • 18
  • 245
  • 284
0

To debug try:

app.config['SQLALCHEMY_DATABASE_URI'] = \
    'mysql+oursql://' + os.environ.get('DB_USR','NO_USER') \
    + ':' + os.environ.get('DB_PASSWD', 'NOPASSWD')+'@' \
    + os.environ.get('DB_HOST', 'NO_HOST') + '/school_new'

And log/print app.config['SQLALCHEMY_DATABASE_URI'].

Stephen Rauch
  • 47,830
  • 31
  • 106
  • 135
0

When the key you request the value of doesn't exist in the dictionary, .get() returns None.

So, given the error you're getting, it appears that there is no 'DB_HOST' in os.environ.

If there's some default value ('localhost' perhaps?) that makes sense for you to use in such cases, you can add it as the second parameter in your call to .get(), and then that value will be returned rather than None whenever the key doesn't exist.

os.environ.get('DB_HOST', 'localhost')

And if it's at all possible that the other keys ('DB_USR' and 'DB_PASSWD') might not exist, you should either add appropriate default values for them, or employ some form of error handling.

Dan
  • 557
  • 5
  • 12
0

As others have mentioned, using .get() on a dictionary will result in a None if the value does not exist:

get(key[, default])

Return the value for key if key is in the dictionary, else default. If default is not given, it defaults to None, so that this method never raises a KeyError.

It's a dictionary, so you could even do things like os.environ['DB_HOST'] instead of using .get(). Why? Because then you'd get an error on startup if the value didn't exist! Which might be nifty in something so critical to your application. :)

Okay, so apparently os.environ.get('DB_HOST') in your code has returned None. Why is that?

os.environ gives you access to the operating system's environment variables from the shell. Apparently, the variable DB_HOST hasn't been set anywhere!

To solve your problem, you'll have to set the environment variable for DB_HOST in your OS, or else provide the information in some other way. Personally, I like passing these values in as command-line arguments via argparse, but that's up to you!


In case you really want to use the OS's environment, I'll give you an example of setting a variable in bash (my shell). You'd have to look up parallel instructions for other shells.

From the bash command line:

$ export TEST_VAL="My hovercraft is full of eels."
$ python
(...)
>>> import os
>>> os.environ['TEST_VAL']
'My hovercraft is full of eels.'

Note that use of os.environ in Python cannot set a new value for this variable outside of its own interactions. That is to say:

>>> os.environ['TEST_VAL'] = "new value"
>>> exit()
$ echo $TEST_VAL
My hovercraft is full of eels.
Pierce Darragh
  • 2,072
  • 2
  • 16
  • 29