Sunday, March 30, 2014

Location of the Procfile

Keep your Procfile in your project's top directory!  Otherwise, gunicorn (the server running your app) will not be able to see the Procfile!


/Users/christopherspears/PyDevel/tapeworm_django/
Procfile
README.md
requirements.txt
tapeworm/
  __init__.py
  __init__.pyc
  drawings/
  manage.py
  tapeworm/
  templates/

Friday, March 28, 2014

Deploying a Python Django app to Heroku

Today I decided to try to deploy my app to Heroku.  Fortunately, I found a pretty good tutorial that shows me how to do this:

https://devcenter.heroku.com/articles/getting-started-with-django

I will be detailing my trials and tribulations as I attempt to do this.  My first issue was that I could not get foreman to work.  The gem foreman is not part of the django-toolbelt.  It is part of the Heroku ToolBelt.  I fixed this by uninstalling and reinstalling the gem.  I then discovered that the Procfile I created needed to be at the same level as the manage.py file.  Otherwise, I would get a bunch of this:

(tapeworm_django)christohersmbp2:tapeworm_django christopherspears$ foreman start
11:18:52 web.1  | started with pid 2122
11:18:52 web.1  | 2014-03-28 11:18:52 [2122] [INFO] Starting gunicorn 18.0
11:18:52 web.1  | 2014-03-28 11:18:52 [2122] [INFO] Listening at: http://0.0.0.0:5000 (2122)
11:18:52 web.1  | 2014-03-28 11:18:52 [2122] [INFO] Using worker: sync
11:18:52 web.1  | 2014-03-28 11:18:52 [2125] [INFO] Booting worker with pid: 2125
11:18:52 web.1  | 2014-03-28 11:18:52 [2125] [ERROR] Exception in worker process:
11:18:52 web.1  | Traceback (most recent call last):
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/arbiter.py", line 495, in spawn_worker
11:18:52 web.1  |     worker.init_process()
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/workers/base.py", line 106, in init_process
11:18:52 web.1  |     self.wsgi = self.app.wsgi()
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/app/base.py", line 114, in wsgi
11:18:52 web.1  |     self.callable = self.load()
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 62, in load
11:18:52 web.1  |     return self.load_wsgiapp()
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 49, in load_wsgiapp
11:18:52 web.1  |     return util.import_app(self.app_uri)
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/util.py", line 354, in import_app
11:18:52 web.1  |     __import__(module)
11:18:52 web.1  | ImportError: No module named tapeworm.wsgi
11:18:52 web.1  | Traceback (most recent call last):
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/arbiter.py", line 495, in spawn_worker
11:18:52 web.1  |     worker.init_process()
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/workers/base.py", line 106, in init_process
11:18:52 web.1  |     self.wsgi = self.app.wsgi()
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/app/base.py", line 114, in wsgi
11:18:52 web.1  |     self.callable = self.load()
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 62, in load
11:18:52 web.1  |     return self.load_wsgiapp()
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/app/wsgiapp.py", line 49, in load_wsgiapp
11:18:52 web.1  |     return util.import_app(self.app_uri)
11:18:52 web.1  |   File "/Users/christopherspears/.virtualenvs/tapeworm_django/lib/python2.7/site-packages/gunicorn/util.py", line 354, in import_app
11:18:52 web.1  |     __import__(module)
11:18:52 web.1  | ImportError: No module named tapeworm.wsgi
11:18:52 web.1  | 2014-03-28 11:18:52 [2125] [INFO] Worker exiting (pid: 2125)
11:18:52 web.1  | 2014-03-28 11:18:52 [2122] [INFO] Shutting down: Master
11:18:52 web.1  | 2014-03-28 11:18:52 [2122] [INFO] Reason: Worker failed to boot.
11:18:52 web.1  | exited with code 3

11:18:52 system | sending SIGTERM to all processes

By the way, I always forget to do this when creating a Heroku app:

(tapeworm_django)christohersmbp2:tapeworm_django christopherspears$ heroku apps:create tapeworm
Creating tapeworm... done, stack is cedar
http://tapeworm.herokuapp.com/ | git@heroku.com:tapeworm.git
Git remote heroku added

Otherwise, Heroku is going to give your app a name like "Flowing Downstream Leaves", which is annoying.  I managed to successfully push my app to Heroku.  The next step is to try to turn it on.

Wednesday, March 26, 2014

Django Json Field

Been looking for a good json field for Django.  I hope this will work:

https://github.com/bradjasper/django-jsonfield

Creating a requirements.txt file

You can create a requirements.txt file for a Python project with pip:
(tapeworm_django)christohersmbp2:tapeworm_django christopherspears$ pip freeze > requirements.txt
(tapeworm_django)christohersmbp2:tapeworm_django christopherspears$ cat requirements.txt 
Django==1.6.2
psycopg2==2.5.2

wsgiref==0.1.2

Setting environmental variables in virtualenv

I am taking a stab at my first Django project.  As with all web apps, I am concerned with security, so I decided to set my SECRET_KEY as an environmental variable.  Fortunately, this is not too hard to do if you have virtualenvwrapper.  Here is a pretty good Stack Overflow thread about that:

http://stackoverflow.com/questions/9554087/setting-an-environment-variable-in-virtualenv

After reading the thread multiple times, I did the following. First I located the bin directory of the virtual environment I was using ($HOME/.virtualenvs/tapeworm_django/bin).  Inside I found the postactivate hook, which is an executable file and modified it like so:

#!/bin/bash
# This hook is run after this virtualenv is activated.


export SECRET_KEY=myKey

Then I found the predactivate hook and added the following:

#!/bin/bash
# This hook is run before this virtualenv is deactivated.

unset SECRET_KEY

Now will the SECRET_KEY variable will be set and unset when I decided to work on the tapeworm_django virtual environment:

christohersmbp2:tapeworm_django christopherspears$ workon tapeworm_django
(tapeworm_django)christohersmbp2:tapeworm_django christopherspears$ echo $SECRET_KEY
myKey
(tapeworm_django)christohersmbp2:tapeworm_django christopherspears$ deactivate
christohersmbp2:tapeworm_django christopherspears$ echo $SECRET_KEY

christohersmbp2:tapeworm_django christopherspears$

Now in settings.py file of the project configuration directory, I set secret key like so:

SECRET_KEY =  os.environ['SECRET_KEY']

Sunday, March 23, 2014

Comparing Three Python Web Frameworks

I have been spending a lot of time noodling around with different Python web frameworks.  Specifically, I have played with Django, Bottle, and Pyramid.  Here are my thoughts on them.  Since the first MVC framework I learned is Rails, I will be comparing some of them to Rails.

1. Django

Basically Python's answer to Rails (or vice versa?).  Django is a powerful, fully developed, and very structured framework that can be used to make professional web apps.  If you want a job, this is the one to learn.  One significant difference between Rails and Django is that you work on Django project, which can include multiple apps, where in Rails you just work on one app.  This promotes code reuse because if you are clever you can use one Django app in several projects.

Models are called models in both Django and Rails.  What are called controllers in Rails are called views in Django, and views in Rails are called templates.  Django does not have a concept of scaffolding to speed up setting up routes like Rails does.  You have to write all of the routes out.

2. Bottle

Bottle interests me because I like the idea of carrying an app in my pocket.  Seriously, the code for the Bottle framework is contained in one file!  One way to install Bottle is to just download the bottle.py file.  My guess is that the Ruby equivalent is Sinatra.

Bottle is very minimal, and you have to build everything from the ground up, which can be liberating or frustrating depending on your personality, unlike Django, which gives you a lot of bells and whistles out of the box.

3. Pyramid

Pyramid wants you to have your cake and eat it too.  You can write a very minimal web app (like the "Hello World" app you write in one of Pyramid's tutorials), or you can write a larger app using a directory structure similar to Django.  Flexibility seems to be the trademark of this framework.

Saturday, March 22, 2014

Install twisted in a virtual environment on OS X Mavericks

A recruiter suggested that I look at twisted before having an interview with a client.  Strangely enough, learning how to install twisted in a virtual environment on OS X Mavericks is not easy probably because some of twisted is installed in OS X anyway.  However, I was not using the system python.  I was using the python I installed with brew, so I kept getting this error message:

ImportError: No module named twisted

After poking around a little bit, I finally broke down and asked Stack Overflow:


First, I made a virtual environment called try_twisted, and then I installed twisted with pip:

(try_twisted)christohersmbp2:try_twisted christopherspears$ pip install twisted

Now twisted works:

(try_twisted)christohersmbp2:try_twisted christopherspears$ python
Python 2.7.5 (default, Aug 25 2013, 00:04:04) 
[GCC 4.2.1 Compatible Apple LLVM 5.0 (clang-500.0.68)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import twisted
>>> 

Monday, March 10, 2014

“Cross origin requests are only supported for HTTP.”

Got a really fun error message today when trying to load a html file with Paper.js using file:///.  Turns out for I needed to actually spin up a server to load the file.  The explanation why can be found here:


Spinning up a server is really easy thanks to the magic of Python:

python -m SimpleHTTPServer


Friday, March 7, 2014

Fixing mkvirtualenv after installing OS X Mavericks

As expected, installing OS X Mavericks caused a few of my hacker tools to break.  The most annoying issue was getting virtualenv and virtualenvwrapper to work again.  Figured it out after 48 hours:


Yes, dealing with !@#! like this is a pain, but I did learn a lot by fixing this.