pymssql in AWS Lambda

I’m currently writing a Django web app that pulls information from a MS SQL database. Of course, I want this application to be run as cost effectively as possible so I’m placing the Django app in AWS Lambda using Zappa for deployment. I gave a talk on using AWS Lambda and Zappa for a Django project at PSU MacAdmins 2017 called Imaging in 50+ Locations. Needless to say, I love deploying Django apps this way. (This post won’t go into how to use Zappa.)

However, I ran into a problem. The open-source MS SQL library I’m using in my app is pymssql. This is a great library that works on many platforms including AWS Lambda (which is basically just the AWS EC2 Linux AMI). It even supports the latest version of Python 3.6 which I’m also using. However, pymssql relies on FreeTDS to talk to MS SQL. This normally wouldn’t be a problem since the team over pymssql also includes an option to build the software on your machine with a bundled version of FreeTDS in precompiled wheels. Sounds great until you see this error in the browser:
Screen Shot 2017-11-15 at 10.39.56 AM

The problem arises when you’re using anything greater than Python 3.5. There are no precompiled wheels for Python 3.6 for any platform. This means that when deploying my app from my test machine, a Mac, Zappa doesn’t upload a Linux compatible version of the pymssql library. It uploads a Darwin version. If I deploy from an EC2 Linux instance Zappa will upload a Linux compatible version of pymssql but it’s still missing FreeTDS. The quickest way to solve this would be for the team over at pymssql to release a precompiled Python 3.6 ‘manylinux’ wheel. Until then I need a workaround.

To keep this post short, after much Google’ing I found a solution that works for my environment:

  1. Create an EC2 Linux instance based on the Amazon Linux AMI (ami-6057e21a)
  2. SSH into the instance
  3. Install the most up-to-date version of Python 3.6, FreeTDS, the ‘gcc’ compiler, and ‘git’:
    sudo yum install python36-devel freetds-devel gcc git
  4. Clone your application code from version control:
    git clone [your_code_repo_url]
  5. Create a virtual environment for our code dependencies:
    virtualenv -p $(python3) virtualenv
  6. Activate your virtual environment and change into your code directory:
    source virtualenv/bin/activate && cd [your_code_repo]
  7. Create an environment variable to build pymssql with a bundled version of FreeTDS:
    export PYMSSQL_BUILD_WITH_BUNDLED_FREETDS=1
  8. Install your python dependencies. Make sure to install pymssql from the latest build:
    pip install git+https://github.com/pymssql/pymssql.git
  9. Copy the missing ‘libsybdb.so’ file to site-packages within the virtualenv:
    cp /usr/lib64/libsybdb.so ../virtualenv/lib/python3.6/site-packages/
  10. At this point ‘pymssql’ can run within AWS Lambda with Python 3.6

I would love to get feedback from others on how they run pymssql in AWS Lambda or if my method helps you.

10 thoughts on “pymssql in AWS Lambda

  1. Hi Chase, thanks for posting this- it helped clarify the problem for me. Unfortunately, I still seem to be getting this error, which suggests that even though `libsybdb.so.5` is in (what should be) the right location, the import script or interpreter is looking elsewhere for it. Any insights on how to check for where `importlib/__init__.py` is looking for the .so file?
    Thanks!

    Like

    1. Can you confirm that the libsybdb.so file was copied to the /lib//site-packages directory? If there is any way you can share a gist of your error log from lambda or your application, that might be helpful as well. Feel free to hit me up on Twitter (@chase_tb).

      Like

      1. That’s the ‘virtualenv/lib/python/site-packages’ directory. Sorry I didn’t make that very clear in the first reply.

        Like

  2. Hi Chase! Thank you for posting this 🙂
    I’m trying to follow your steps but am having an issue activating my virtualenv. When I type in the command to activate, I get the error that virtualenv/bin/activate is not a file or directory. I have tried multiple other things, including trying to uninstall virtualenv, but then I get a ‘permission denied’ warning on /usr/local/bin, which is an empty directory…

    Like

    1. It is probably because you haven’t included the ‘source’ command at the beginning. By not running source, you are trying to run the ‘activate’ file directly, which you cannot do. Source executes the contents of the file.

      Like

  3. Hi, I am trying to connect to a Sybase database and get an error even inspite of going through the same setup. I have followed the same set up for SQL server and works perfectly.

    And the error is very generic :

    File “src/pymssql.pyx”, line 642, in pymssql.connect
    pymssql.OperationalError: (20002, b’DB-Lib error message 20002, severity 9:\nAdaptive Server connection failed (SERVERNAME:PORT\n’)

    Any help is appreciated….

    Like

    1. I’m certainly no expert at pymssql and that error is pretty generic. It may even mean there is an issue outside of the pymssql library itself. As this comment suggests (https://github.com/pymssql/pymssql/issues/114#issuecomment-24975829), “I’d recommend posting this instead as a topic on the discussion forum at http://groups.google.com/group/pymssql since it’s not clear that this is a pymssql bug yet. You should mention in your posting what platform you are connecting from (e.g.: Linux, Mac, Windows, etc.), what version of Python you’re using, how you installed pymssql (e.g.: pip install pymssql or python setup.py from code checked out from hg tip, etc.), what version of FreeTDS you have, etc.”

      Like

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.