Zappa icon indicating copy to clipboard operation
Zappa copied to clipboard

How to include Pango/Cairo to use Weasyprint with my Django app?

Open Brachamul opened this issue 7 years ago • 14 comments

Context

I have deployed a simple Django app which uses Weasyprint.

Expected Behavior

The app should produce PDF files, upon request.

Actual Behavior

The app prints the following exception: cannot load library 'pango-1.0': pango-1.0: cannot open shared object file: No such file or directory. Additionally, ctypes.util.find_library() did not manage to locate a library called 'pango-1.0'

Weasyprint requires Pango and Cairo, which normally need to be installed on the host machine.

Possible Fix

@Prasengupta has published a github repo, weasyprint_for_awslambda to help with importing Pango and Cairo. Unfortunately, I dont fully understand what needs to be done. He says I should Step 1: Download the zip file from this repository. Step 2: Include your main handler file in the folder and zip it, upload the zip folder to aws lambda., but I don't know how to do step 2 with Zappa.

Steps to Reproduce

  1. Create a Django app which uses Weasyprint to produce a PDF, for example : weasyprint.HTML("https://www.google.com/").write_pdf()
  2. Push to AWS
  3. Witness the error message

Your Environment

  • Zappa version used: 0.47.0
  • Python version: 3.6
  • The output of pip freeze: https://justpaste.it/7j2sx

Brachamul avatar Nov 02 '18 14:11 Brachamul

@Brachamul have you gotten anywhere with this? I just ran into the same snag and there will be no doubt other packages I'm using that will have the same problem.

mattxbart avatar Nov 06 '18 22:11 mattxbart

Yes I have @mattxbart!

It's actually very simple, I just copied all the files in weasyprint_for_awslambda to my root folder (the one with the zappa_settings.json file).

And it... just worked!

Brachamul avatar Nov 07 '18 10:11 Brachamul

For what it's worth, you don't need the full slate of dependencies there; you can just drop a few .so files into lib/ within your project. Those deps are here: https://www.dropbox.com/s/dpxfow8tpkg2big/weasyprint-dependencies.tar.gz?dl=0

If you want to enable JPGs in the resulting PDF, you'll have to find a way to get the gdk-pixbuf-2.0 library into /usr/lib, but besides that, this works pretty flawlessly.

youcandanch avatar Jan 17 '19 21:01 youcandanch

For what it's worth, you don't need the full slate of dependencies there; you can just drop a few .so files into lib/ within your project. Those deps are here: https://www.dropbox.com/s/dpxfow8tpkg2big/weasyprint-dependencies.tar.gz?dl=0

If you want to enable JPGs in the resulting PDF, you'll have to find a way to get the gdk-pixbuf-2.0 library into /usr/lib, but besides that, this works pretty flawlessly.

What do you mean "you'll have to find a way"?, does lambda not support /usr/ folder is that why? I'm trying to setup the weasyprint to work with lambda/zappa but I also need images to work.

And which library requires the pixbuf to be in the usr folder? Maybe that can be modified?

mojimi avatar Mar 04 '19 12:03 mojimi

@youcandanch Another thing I noticed is that your libs are outdated (as mentioned by weasyprint), do you happen to know how to update them?

mojimi avatar Mar 06 '19 13:03 mojimi

What do you mean "you'll have to find a way"?, does lambda not support /usr/ folder is that why? I'm trying to setup the weasyprint to work with lambda/zappa but I also need images to work.

What I ended up doing was this:

        "environment_variables": {
            "GDK_PIXBUF_MODULE_FILE": "/var/task/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
        },

That takes care of it as long as what you take what I have in that tar and put it into /var/task.

@youcandanch Another thing I noticed is that your libs are outdated (as mentioned by weasyprint), do you happen to know how to update them?

You'd have to compile a whole lot of stuff on Amazon Linux 2. I ended up throwing up my hands in annoyance on it.

youcandanch avatar Apr 05 '19 20:04 youcandanch

This is how I got Pango (with cairo) on ElasticBeanstalk - in case it helps anyone else

First, pip install -r requirements.txt was run before pip upgrade, so I changed my 02_initial.config to

container_commands:
  01_upgrade_pip:
    command: "source /opt/python/run/venv/bin/activate && pip install --upgrade pip"
    leader_only: true
  02_upgradde_setuptools:
    command: "source /opt/python/run/venv/bin/activate && pip install --upgrade setuptools"
    leader_only: true
  03_requirements:
    command: "source /opt/python/run/venv/bin/activate && pip install -r requirements.txt"
    leader_only: true



files:
  "/opt/python/run/venv/pip.conf":
    mode: "000755"
    owner: root
    user: root
    content: |
      [global]
      no-cache-dir=false

option_settings:
  "aws:elasticbeanstalk:application:environment":
    DJANGO_SETTINGS_MODULE: "my-app.settings"
    "PYTHONPATH": "/opt/python/current/app/am-app:$PYTHONPATH"
  "aws:elasticbeanstalk:container:python":
    WSGIPath: my-app/my-app/wsgi.py
    NumProcesses: 6
    NumThreads: 20
  "aws:elasticbeanstalk:container:python:staticfiles":
    "/static/": "my-app/static/"

I then started getting an error with unable to find pango. So I amended my 01_packages.config

 packages:
  yum:
    git: []
    ...
    cairo-devel: []
    pango: []

HenryMehta avatar Mar 29 '20 08:03 HenryMehta

Not sure I recommend this, but I have it working by including libpangoft2-1.0.so.0 , pango-1.0 , and pangocairo-1.0 as binaries in the root of my code tree. It gets zipped up and deployed with the zappa package to lambda and works, though fonts are a bit tricky and it throws some obnoxious warnings in the logs. Note that my project is using python 2.7. Possibly relevant from requirements.txt:

cairocffi==0.8.1 CairoSVG==1.0.22 WeasyPrint==0.42.3

pangocairo-1.0[+2].zip

jumprope-jesse avatar Mar 31 '20 14:03 jumprope-jesse

I did: "environment_variables": { "GDK_PIXBUF_MODULE_FILE": "/var/task/lib/gdk-pixbuf-2.0/2.10.0/loaders.cache" }, It doesn't work :( (I have in the correct path, but it doesn't work jpg support...

obedmacallums avatar Apr 20 '20 02:04 obedmacallums

FWIW, for me the issue was fixed by doing a sudo apt-get install libpangocairo-1.0-0 (Ubuntu 20.04 LTS).

I no longer have the error OSError: cannot load library 'pangocairo-1.0': pangocairo-1.0: cannot open shared object file: No such file or directory. Additionally, ctypes.util.find_library() did not manage to locate a library called 'pangocairo-1.0'.

opbod avatar Oct 26 '20 18:10 opbod

This is how I got Pango (with cairo) on ElasticBeanstalk - in case it helps anyone else

First, pip install -r requirements.txt was run before pip upgrade, so I changed my 02_initial.config to

container_commands:
  01_upgrade_pip:
    command: "source /opt/python/run/venv/bin/activate && pip install --upgrade pip"
    leader_only: true
  02_upgradde_setuptools:
    command: "source /opt/python/run/venv/bin/activate && pip install --upgrade setuptools"
    leader_only: true
  03_requirements:
    command: "source /opt/python/run/venv/bin/activate && pip install -r requirements.txt"
    leader_only: true



files:
  "/opt/python/run/venv/pip.conf":
    mode: "000755"
    owner: root
    user: root
    content: |
      [global]
      no-cache-dir=false

option_settings:
  "aws:elasticbeanstalk:application:environment":
    DJANGO_SETTINGS_MODULE: "my-app.settings"
    "PYTHONPATH": "/opt/python/current/app/am-app:$PYTHONPATH"
  "aws:elasticbeanstalk:container:python":
    WSGIPath: my-app/my-app/wsgi.py
    NumProcesses: 6
    NumThreads: 20
  "aws:elasticbeanstalk:container:python:staticfiles":
    "/static/": "my-app/static/"

I then started getting an error with unable to find pango. So I amended my 01_packages.config

 packages:
  yum:
    git: []
    ...
    cairo-devel: []
    pango: []

Thanks to you. I had the same problem and your solution worked perfectly.

elydev01 avatar Dec 19 '22 16:12 elydev01

How to solve the error on windows machine? I have installed GTK-3 and trying to deploy my django app on elastic beanstalk . What changes do I need to make in django.config?

Niiteesh006 avatar Jun 28 '23 10:06 Niiteesh006

Hi @Niiteesh006 Elastic Beanstalk is a managed deployment from AWS. You may need to look into its config or you need to use an EC2 instance.

souravjamwal77 avatar Jun 29 '23 06:06 souravjamwal77

@Niiteesh006 It depends on which ElasticBeanstalk environment you're deploying to. Different versions have different version of Pango / Cairo so you might have to include the download yourself to get a more recent version (if needed). You can see how I did it above for AWSLinux2 instance running Python3.8

HenryMehta avatar Jun 29 '23 06:06 HenryMehta