This Blog continues on http://aliafshar.github.io/blog

Thursday, March 15, 2007

Using pexpect to control Django manage.py

In the early stages of developing a Django application, I was deleting my sqlite database, and rerunning:


python manage.py syncdb


Every few minutes as the database models were changing. You might consider this some kind of evil thing to do, because we should all have our database models in concrete before writing any code but I am not that organised.

One thing that was really distressing me was the fact that each time I ran a syncdb, I had to enter details for my default admin user.

  • Username
  • Email address
  • Password
  • Repeart Password
This was fine for the first 400 times, then I got bored. The solution was to use pexpect. (There are probably command line options that you can give manage.py, but finding them out would have been more effort than this hack)

Pexpect, http://pexpect.sourceforge.net/ is a pure python module for running external commands and controlling them as if you were a user. It has good documentation, and is perfect for needs of this nature.

A quick browse through the excellent documentation, and we were away. Here is the code:


PASSWORD = '123' # replace this with something good
EMAIL = 'aafshar@gmail.com'

import pexpect

# spawn the child process
child = pexpect.spawn('python manage.py syncdb')

# Wait for the application to give us this text (a regular expression)
child.expect('Would you like to create one now.*')

# Send this line in response
child.sendline('yes')

# Again wait for this, and send what is needed
child.expect('Username.*')

# A blank string for the default username
child.sendline('')

# And so it goes on
child.expect('E-mail.*')
child.sendline(EMAIL)
child.expect('Password.*')
child.sendline(PASSWORD)
child.expect('Password.*')
child.sendline(PASSWORD)

# This means wait for the end of the child's output
child.expect(pexpect.EOF, timeout=None)


And we are done. This runs the command, and enters the correct details without having to be interactive, and saving a load of time and typing.

I actually combined this script with an initial data-import setup script which loaded the database with the initial data, for added fruitiness.