Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Pyscopg DB - Error Adding Persistence to code

I am working on an online project by Udacity. I am using vagrant configured by them, to run the server containing the Database. Unfortunately when I tried to give the code persistence, the server returns an error everytime. I am new to python so please forgive any obvious mistakes.

Here is the error :

Serving HTTP on port 8000...
Traceback (most recent call last):
  File "/usr/lib/python2.7/wsgiref/handlers.py", line 85, in run
    self.result = application(self.environ, self.start_response)
  File "forum.py", line 95, in Dispatcher
    return DISPATCH[page](env, resp)
  File "forum.py", line 68, in Post
    length = int(env.get('CONTENT_LENGTH', 0))
ValueError: invalid literal for int() with base 10: ''
10.0.2.2 - - [06/Jan/2016 04:44:16] "GET /post HTTP/1.1" 500 59
10.0.2.2 - - [06/Jan/2016 04:44:16] "GET /favicon.ico HTTP/1.1" 404 22

And this is the code that I have changed in forumdb.py :

#
# Database access functions for the web forum.
# 

import psycopg2

## Database connection

def GetAllPosts():
    DB = psycopg2.connect("dbname=forum")
    c = DB.cursor()
    c.execute("SELECT time, content FROM posts ORDER BY time DESC")
    posts = ({'content': str(row[1]), 'time': str(row[0])}
             for row in c.fetchall())

    # This returns a dictionary -- returning just c.fetchall() will return a list of tuples

    DB.close()
    return posts

def AddPost(content):
    DB = psycopg2.connect("dbname=forum")
    c = DB.cursor()
    c.execute("INSERT INTO posts (content) values ('%s')" % content)
    DB.commit()
    DB.close()

forum.py - this file renders the html bringing data from the DB : http://pastebin.com/ZiHWiiwr

Please help !

like image 566
Abhishek Ghosh Avatar asked Sep 26 '22 18:09

Abhishek Ghosh


2 Answers

You're querying the WSGI environment with length = int(env.get('CONTENT_LENGTH', 0)) (forum.py:68). I just ran a sample WSGI server (example code taken from the python docs), which outputs all the available environment-variables upon request:

from wsgiref.util import setup_testing_defaults
from wsgiref.simple_server import make_server

# A relatively simple WSGI application. It's going to print out the
# environment dictionary after being updated by setup_testing_defaults
def simple_app(environ, start_response):
    setup_testing_defaults(environ)

    status = '200 OK'
    headers = [('Content-type', 'text/plain')]

    start_response(status, headers)

    ret = ["%s: %s\n" % (key, value)
           for key, value in environ.iteritems()]
    return ret

httpd = make_server('', 8000, simple_app)
print "Serving on port 8000..."
httpd.serve_forever()

The output I'm getting when querying the test-server is (among a lot of other variables):

SERVER_PORT: 8000
CONTENT_LENGTH: 
GLADE_CATALOG_PATH: :

You see that the CONTENT_LENGTH variable is empty. This seems to be the case in your application as well.

If the env-dictionary is now queried with env.get('CONTENT_LENGTH', 0), The CONTENT_LENGTH-key is actually found, but it's value is an empty string - that's why the get() method returns '' and not your specified default value 0.

Since an empty string can't be converted to an int, you're getting the ValueError.

Try catching the exception and your code should work:

try:
    length = int(env.get("CONTENT_LENGTH", 0))
except ValueError:
    length = 0
like image 148
andreas-hofmann Avatar answered Oct 20 '22 15:10

andreas-hofmann


Your current error is happening because of the line

length = int(env.get('CONTENT_LENGTH', 0))

in forum.py. Basically the key CONTENT_LENGTH exists and it is an empty string and an empty string can't be converted to an int. Change that line to

length = int(env.get('CONTENT_LENGTH')) if env.get('CONTENT_LENGTH') else 0

Since you're new to Python there are a couple things you should know about the modified line First it is know as a conditional expression, second empty strings in Python are have a boolean value of False so when

  • env.get('CONTENT_LENGTH') returns an empty string then length is assigned 0
  • env.get('CONTENT_LENGTH') returns a non empty string or an integer then int converts that value to it's integer representation
  • env.get('CONTENT_LENGTH') returns a 0 (which has a boolean value of false) then 0 is assigned
like image 2
John Avatar answered Oct 20 '22 15:10

John