How to include Pango/Cairo to use Weasyprint with my Django app?
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
- Create a Django app which uses Weasyprint to produce a PDF, for example :
weasyprint.HTML("https://www.google.com/").write_pdf() - Push to AWS
- 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 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.
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!
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.
For what it's worth, you don't need the full slate of dependencies there; you can just drop a few
.sofiles intolib/within your project. Those deps are here: https://www.dropbox.com/s/dpxfow8tpkg2big/weasyprint-dependencies.tar.gz?dl=0If you want to enable JPGs in the resulting PDF, you'll have to find a way to get the
gdk-pixbuf-2.0library 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?
@youcandanch Another thing I noticed is that your libs are outdated (as mentioned by weasyprint), do you happen to know how to update them?
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.
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: []
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
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...
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'.
This is how I got Pango (with cairo) on ElasticBeanstalk - in case it helps anyone else
First,
pip install -r requirements.txtwas run before pip upgrade, so I changed my02_initial.configtocontainer_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 my01_packages.configpackages: yum: git: [] ... cairo-devel: [] pango: []
Thanks to you. I had the same problem and your solution worked perfectly.
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?
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.
@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