Search code examples
postgresqlpython-3.xherokutornado

Postgres Connection Issues with Heroku in Tornado


I'm running a tornado application on Heroku, and all has been going well up untill this point, where I'm trying to add a Heroku Postgres add-on. At this point, I can connect locally using Heroku's python guide while exporting DATABASE_URL=postgres:///$(whoami) as shown here. However, when I run heroku local with the DATABASE_URL given from heroku config:get DATABASE_URL, I get the follow stack trace:

[OKAY] Loaded ENV .env File as KEY=VALUE Format
5:48:26 PM web.1 |  Traceback (most recent call last):
5:48:26 PM web.1 |    File "src/myapp/app.py", line 61, in <module>
5:48:26 PM web.1 |      main()
5:48:26 PM web.1 |    File "src/myapp/app.py", line 55, in main
5:48:26 PM web.1 |      app = MyApplication()
5:48:26 PM web.1 |    File "src/myapp/app.py", line 35, in __init__
5:48:26 PM web.1 |      self.db = self.connect_to_db()
5:48:26 PM web.1 |    File "src/myapp/app.py", line 49, in connect_to_db
5:48:26 PM web.1 |      port=url.port
5:48:26 PM web.1 |    File "/usr/lib/python3/dist-packages/psycopg2/__init__.py", line 164, in connect
5:48:26 PM web.1 |      conn = _connect(dsn, connection_factory=connection_factory, async=async)
5:48:26 PM web.1 |  psycopg2.OperationalError: FATAL:  database "heroku_username" does not exist

My code for running the tornado application is shown below:

from os import environ

from psycopg2 import connect

from tornado.ioloop import IOLoop
from tornado.options import define
from tornado.options import options
from tornado.options import parse_command_line
from tornado.web import Application

from urllib.parse import urlparse
from urllib.parse import uses_netloc


define('debug', default=True, help='debug is on or not')
define('port', default=8888, help='run on given port', type=int)


class MyApplication(Application):

    def __init__(self):
        handlers = [
            (r'/health', HealthCheckHandler)
        ]
        settings = dict(debug=options.debug)

        self.db = self.connect_to_db()
        Application.__init__(self, handlers, **settings)

    def connect_to_db(self):
        """Connects to the database instance."""
        uses_netloc.append('postgres')
        url = urlparse(environ['DATABASE_URL'])
        print(url.username)

        conn = connect(
            database=url.path[1:0],
            user=url.username,
            password=url.password,
            host=url.hostname,
            port=url.port
        )


def main():
    parse_command_line()
    app = MyApplication()
    app.listen(options.port)
    IOLoop.current().start()


if __name__ == '__main__':
    main()

Solution

  • Well, it turns out I wanted to be an idiot today. If anyone's interested in the answer, in connect_to_db in the connection function, I put database=url.path[1:0] instead of database=url.path[1:]. Effectively, I had no database specified.