Kozea / CairoSVG

Convert your vector images
https://courtbouillon.org/cairosvg
GNU Lesser General Public License v3.0
770 stars 150 forks source link

"OSError: no library called "cairo-2" was found" after install #354

Closed AndrewHartAR closed 2 years ago

AndrewHartAR commented 2 years ago

I've been trying to install cairosvg, but run into errors. For example, I've tried installing via: pip3 install cairosvg pip install cairosvg brew install cairo

But then just running cairosvg in Terminal, I get this error:

Traceback (most recent call last):
  File "/Users/andrew/Environments/analysis/bin/cairosvg", line 5, in <module>
    from cairosvg.__main__ import main
  File "/Users/andrew/Environments/analysis/lib/python3.10/site-packages/cairosvg/__init__.py", line 26, in <module>
    from . import surface  # noqa isort:skip
  File "/Users/andrew/Environments/analysis/lib/python3.10/site-packages/cairosvg/surface.py", line 9, in <module>
    import cairocffi as cairo
  File "/Users/andrew/Environments/analysis/lib/python3.10/site-packages/cairocffi/__init__.py", line 48, in <module>
    cairo = dlopen(
  File "/Users/andrew/Environments/analysis/lib/python3.10/site-packages/cairocffi/__init__.py", line 45, in dlopen
    raise OSError(error_message)  # pragma: no cover
OSError: no library called "cairo-2" was found
no library called "cairo" was found
no library called "libcairo-2" was found
cannot load library 'libcairo.so.2': dlopen(libcairo.so.2, 0x0002): tried: 'libcairo.so.2' (no such file), '/usr/local/lib/libcairo.so.2' (no such file), '/usr/lib/libcairo.so.2' (no such file), '/Users/andrew/libcairo.so.2' (no such file), '/usr/local/lib/libcairo.so.2' (no such file), '/usr/lib/libcairo.so.2' (no such file)
cannot load library 'libcairo.2.dylib': dlopen(libcairo.2.dylib, 0x0002): tried: 'libcairo.2.dylib' (no such file), '/usr/local/lib/libcairo.2.dylib' (no such file), '/usr/lib/libcairo.2.dylib' (no such file), '/Users/andrew/libcairo.2.dylib' (no such file), '/usr/local/lib/libcairo.2.dylib' (no such file), '/usr/lib/libcairo.2.dylib' (no such file)
cannot load library 'libcairo-2.dll': dlopen(libcairo-2.dll, 0x0002): tried: 'libcairo-2.dll' (no such file), '/usr/local/lib/libcairo-2.dll' (no such file), '/usr/lib/libcairo-2.dll' (no such file), '/Users/andrew/libcairo-2.dll' (no such file), '/usr/local/lib/libcairo-2.dll' (no such file), '/usr/lib/libcairo-2.dll' (no such file)

It's similar if I run import cairosvg in Python:

  File "/Users/andrew/Code/ai/ai4/hmm.py", line 1, in <module>
    import cairosvg
  File "/Users/andrew/Environments/analysis/lib/python3.10/site-packages/cairosvg/__init__.py", line 26, in <module>
    from . import surface  # noqa isort:skip
  File "/Users/andrew/Environments/analysis/lib/python3.10/site-packages/cairosvg/surface.py", line 9, in <module>
    import cairocffi as cairo
  File "/Users/andrew/Environments/analysis/lib/python3.10/site-packages/cairocffi/__init__.py", line 48, in <module>
    cairo = dlopen(
  File "/Users/andrew/Environments/analysis/lib/python3.10/site-packages/cairocffi/__init__.py", line 45, in dlopen
    raise OSError(error_message)  # pragma: no cover
OSError: no library called "cairo-2" was found
no library called "cairo" was found
no library called "libcairo-2" was found
cannot load library 'libcairo.so.2': dlopen(libcairo.so.2, 0x0002): tried: 'libcairo.so.2' (no such file), '/usr/local/lib/libcairo.so.2' (no such file), '/usr/lib/libcairo.so.2' (no such file), '/Users/andrew/Code/ai/ai4/libcairo.so.2' (no such file), '/usr/local/lib/libcairo.so.2' (no such file), '/usr/lib/libcairo.so.2' (no such file)
cannot load library 'libcairo.2.dylib': dlopen(libcairo.2.dylib, 0x0002): tried: 'libcairo.2.dylib' (no such file), '/usr/local/lib/libcairo.2.dylib' (no such file), '/usr/lib/libcairo.2.dylib' (no such file), '/Users/andrew/Code/ai/ai4/libcairo.2.dylib' (no such file), '/usr/local/lib/libcairo.2.dylib' (no such file), '/usr/lib/libcairo.2.dylib' (no such file)
cannot load library 'libcairo-2.dll': dlopen(libcairo-2.dll, 0x0002): tried: 'libcairo-2.dll' (no such file), '/usr/local/lib/libcairo-2.dll' (no such file), '/usr/lib/libcairo-2.dll' (no such file), '/Users/andrew/Code/ai/ai4/libcairo-2.dll' (no such file), '/usr/local/lib/libcairo-2.dll' (no such file), '/usr/lib/libcairo-2.dll' (no such file)

If I run brew list, cairo is listed. If I run pip list, the same thing:

cairocffi       1.3.0
CairoSVG        2.5.2
cffi            1.15.0
cssselect2      0.4.1
cycler          0.11.0
defusedxml      0.7.1
drawSvg         1.8.3
imageio         2.13.5
kiwisolver      1.3.2
matplotlib      3.4.3
numpy           1.21.3
pandas          1.3.4
Pillow          8.4.0
pip             21.3.1
plotly          5.3.1
pycparser       2.21
pyparsing       3.0.4
python-dateutil 2.8.2
pytz            2021.3
setuptools      58.3.0
six             1.16.0
tenacity        8.0.1
tinycss2        1.1.1
webencodings    0.5.1
wheel           0.37.0

I'm running macOS 12.0.1, on an M1 Mac (which I think may be a hint towards the problem).

liZe commented 2 years ago

Hello!

If you want to use CairoSVG with Homebrew (and that’s a good idea), you have to use Homebrew’s Python. The pip3 and python3 (not pip, not python) are supposed to be the ones provided by Homebrew, so if you create your virtual environment (that’s currently in /Users/andrew/Environments/analysis/ according to your backtrace) using python3 everything should work.

If python3 is not Homebrew’s Python (you can check that using which python3), you can find Homebrew’s Python in $(brew --prefix)/opt/python/libexec/bin as explained in Homebrew’s Python documentation.

AndrewHartAR commented 2 years ago

So I'm using my virtual environment, the one you mentioned. The command for finding homebrew's Python didn't work, but I did brew info python3 and got:

Python has been installed as
  /opt/homebrew/bin/python3

Doing python3 then running import cairosvg gives the same error as above.

I don't necessarily want to use CairoSVG with Homebrew. Let me explain my goal: I want to use a Python package called drawSvg, which uses CairoSVG to convert from SVG to PNG. I have my virtual environment. So that's my goal.

I have done pip install drawSvg, and also pip install cairosvg, and brew install cairo. Can you tell me what I should be doing instead in order to run this?

liZe commented 2 years ago

Did you use Homebrew’s Python to create the virtual environment? It’s mandatory if you want to use Homebrew’s packages in your venv.

AndrewHartAR commented 2 years ago

How do I check that? I'm happy to create a new virtualenv for testing this. Outside of my environment, if I call which python, I get: /Users/andrew/.asdf/shims/python

If I call brew info python I get:

Python has been installed as
  /opt/homebrew/bin/python3

It's possible I might have setup virtualenv using conda, because this didn't work via brew for M1 Macs. cairo 1.16.0 is installed within conda, however.

liZe commented 2 years ago

How do I check that?

That’s hard to know. Creating a new one is probably the best way to be sure.

Outside of my environment, if I call which python, I get: /Users/andrew/.asdf/shims/python

You have to use python3, not python 😃.

AndrewHartAR commented 2 years ago

/Users/andrew/.asdf/shims/python3

I'm just trying to find out... how do I install CairoSVG?

liZe commented 2 years ago

/Users/andrew/.asdf/shims/python3

It means that you have another custom version of Python installed, that’s why it doesn’t work.

I'm just trying to find out... how do I install CairoSVG?

What you have to do is:

lifenautjoe commented 2 years ago

/Users/andrew/.asdf/shims/python3

It means that you have another custom version of Python installed, that’s why it doesn’t work.

I'm just trying to find out... how do I install CairoSVG?

What you have to do is:

  • create a new virtual environment: /opt/homebrew/bin/python3 -m venv /Users/andrew/Environments/new_analysis/
  • activate the virtual environment: source /Users/andrew/Environments/new_analysis/bin/activate
  • install CairoSVG: pip install cairosvg
  • check that cairosvg works: cairosvg --help

I did everything, it still does not work.

Even if it did, this whole way of this to work is entirely broken...

I'm just gonna use another library to convert one svg to a png instead of bringing god knows how many system level deps and hacky-wacky config into our project.

liZe commented 2 years ago

I'm just gonna use another library to convert one svg to a png instead of bringing god knows how many system level deps and hacky-wacky config into our project.

I hope that you’ll find the library that suits your need.

AndrewHartAR commented 2 years ago

@liZe that person isn't me, just someone I guess with the same issue. Your steps worked for me, thank you.

I would agree that it's an issue that for me to use a library such as drawSvg, I have to setup my entire environment in a specific way to accommodate Cairo. Perhaps this is just a M1 issue, but I'd be worried, if I wanted to run this on a server or host it on GitHub, others would need to do the same complicated process to get it to run?

liZe commented 2 years ago

@liZe that person isn't me, just someone I guess with the same issue.

Oh, OK.

Your steps worked for me, thank you.

😃

Perhaps this is just a M1 issue, but I'd be worried, if I wanted to run this on a server or host it on GitHub, others would need to do the same complicated process to get it to run?

On Linux, it’s pretty easy to setup. As there’s a package manager in all the major distributions of Linux, installing Cairo is really easy and there’s no problem with multiple versions of Python installed on the same system (ie. there’s no need to configure Homebrew). CairoSVG is actually already packaged for many distributions, so you can install it and all its dependencies with just one command.

If you want to use CairoSVG on a server, it will be much easier on Linux.

On macOS and Windows, it’s more complicated, that’s true. Many macOS and Windows users are used to graphical installers, and installing CairoSVG is really different. Even for developers, it’s often more complicated than many libraries to install.

But to be fully honest, we don’t think that it’s that complicated on a fresh macOS installation. You can install it with:

If these steps don’t work, it means that other install software is interfering with CairoSVG: you may have installed other versions of Python, or Cairo, or… It’s really hard to manage these cases, as there are as many cases as there are users. For example, you had Python 3 installed in /Users/andrew/.asdf/shims/python3, and this version was used instead of Homebrew’s one. Why? There’s no way for us to know why. And there’s no way for us to anticipate all these different cases.

And that’s even more complicated on Windows…

We spent countless days (weeks? months?) to make our libraries easier to install. We actually re-wrote our SVG engine (and our HTML/CSS engine) for WeasyPrint, to avoid depending on Cairo and avoid countless issues. It worked quite well, but… CairoSVG deeply relies on Cairo, and we can’t do this for this project. We don’t even have a Mac or a Windows computer.

And, more important, we don’t have enough time.

askpatrickw commented 2 years ago

If you end up looking at this issue and get stuck, checkout this SO suggestion to use inkscape. https://stackoverflow.com/a/7130801/2555335

This worked for me on my M1 Mac.

"""Walk the input folder for each SVG create a PNG in the output folder
"""

from pathlib import Path, PurePath
import subprocess

svg_files = list(Path("input").glob("**/*.svg"))
for svg in svg_files:
    new_png = svg
    np_list = str(new_png).split("/")
    np_list[0] = "output"
    new_png = PurePath("/".join(np_list))
    new_png = new_png.with_suffix(".png")
    print(f"{svg} {new_png}")

    # check if the png folder hierarchy exists or create it
    if not Path(new_png.parent).exists():
        Path(new_png.parent).mkdir(parents=True)
    subprocess.Popen(['inkscape',"-p", f"{str(svg)}", "-o", f"{str(new_png)}", "--export-dpi=1200"])
sblOWPCKCR commented 2 years ago

For those looking for a better workaround, do this before you import cairosvg:

from ctypes.macholib import dyld
dyld.DEFAULT_LIBRARY_FALLBACK.append("/opt/homebrew/lib")

macOS doesn't allow to override any of the standard DYLD environment variables, so this is the least intrusive way of adding /opt/homebrew/lib to the list of paths dlopen() searches in

liZe commented 2 years ago

For those looking for a better workaround, do this before you import cairosvg:

Or just create your virtual environment using Homebrew’s Python, as explained above…

jordanhamill commented 2 years ago

@liZe that advice doesn't work when you run multiple projects using different python versions managed by pyenv.

liZe commented 2 years ago

@liZe that advice doesn't work when you run multiple projects using different python versions managed by pyenv.

Doesn’t Homebrew’s pyenv handle this for you?

jordanhamill commented 2 years ago

M1 Macos 12.2.1 after running brew install pyenv cairo + pyenv install 3.10.3. It's definitely installed as I can see the libs in "/opt/homebrew/lib. Just not sure how to get python to see it without adding an icky dyld.DEFAULT_LIBRARY_FALLBACK line before import. Doesn't seem specifically a cairosvg problem though.

➜  Documents mkdir new_project
➜  Documents cd new_project
➜  new_project pyenv local 3.10.3
➜  new_project python --version
Python 3.10.3
➜  new_project python -m venv .venv
➜  new_project source .venv/bin/activate
(.venv) ➜  new_project python --version
Python 3.10.3
(.venv) ➜  new_project pip install cairosvg
Collecting cairosvg
  Using cached CairoSVG-2.5.2-py3-none-any.whl (45 kB)
Collecting cairocffi
  Using cached cairocffi-1.3.0-py3-none-any.whl
Collecting tinycss2
  Downloading tinycss2-1.1.1-py3-none-any.whl (21 kB)
Collecting defusedxml
  Downloading defusedxml-0.7.1-py2.py3-none-any.whl (25 kB)
Collecting pillow
  Downloading Pillow-9.0.1-1-cp310-cp310-macosx_11_0_arm64.whl (2.7 MB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 2.7/2.7 MB 897.7 kB/s eta 0:00:00
Collecting cssselect2
  Downloading cssselect2-0.5.0-py3-none-any.whl (15 kB)
Collecting cffi>=1.1.0
  Downloading cffi-1.15.0-cp310-cp310-macosx_11_0_arm64.whl (173 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 174.0/174.0 KB 738.8 kB/s eta 0:00:00
Collecting webencodings
  Downloading webencodings-0.5.1-py2.py3-none-any.whl (11 kB)
Collecting pycparser
  Downloading pycparser-2.21-py2.py3-none-any.whl (118 kB)
     ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 118.7/118.7 KB 1.9 MB/s eta 0:00:00
Installing collected packages: webencodings, tinycss2, pycparser, pillow, defusedxml, cssselect2, cffi, cairocffi, cairosvg
Successfully installed cairocffi-1.3.0 cairosvg-2.5.2 cffi-1.15.0 cssselect2-0.5.0 defusedxml-0.7.1 pillow-9.0.1 pycparser-2.21 tinycss2-1.1.1 webencodings-0.5.1
(.venv) ➜  new_project python
Python 3.10.3 (main, Mar 25 2022, 17:24:56) [Clang 13.0.0 (clang-1300.0.29.30)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import cairosvg
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/jordan/Documents/new_project/.venv/lib/python3.10/site-packages/cairosvg/__init__.py", line 26, in <module>
    from . import surface  # noqa isort:skip
  File "/Users/jordan/Documents/new_project/.venv/lib/python3.10/site-packages/cairosvg/surface.py", line 9, in <module>
    import cairocffi as cairo
  File "/Users/jordan/Documents/new_project/.venv/lib/python3.10/site-packages/cairocffi/__init__.py", line 48, in <module>
    cairo = dlopen(
  File "/Users/jordan/Documents/new_project/.venv/lib/python3.10/site-packages/cairocffi/__init__.py", line 45, in dlopen
    raise OSError(error_message)  # pragma: no cover
OSError: no library called "cairo-2" was found
no library called "cairo" was found
no library called "libcairo-2" was found
cannot load library 'libcairo.so.2': dlopen(libcairo.so.2, 0x0002): tried: 'libcairo.so.2' (no such file), '/usr/local/lib/libcairo.so.2' (no such file), '/usr/lib/libcairo.so.2' (no such file), '/Users/jordan/Documents/new_project/libcairo.so.2' (no such file), '/usr/local/lib/libcairo.so.2' (no such file), '/usr/lib/libcairo.so.2' (no such file)
cannot load library 'libcairo.2.dylib': dlopen(libcairo.2.dylib, 0x0002): tried: 'libcairo.2.dylib' (no such file), '/usr/local/lib/libcairo.2.dylib' (no such file), '/usr/lib/libcairo.2.dylib' (no such file), '/Users/jordan/Documents/new_project/libcairo.2.dylib' (no such file), '/usr/local/lib/libcairo.2.dylib' (no such file), '/usr/lib/libcairo.2.dylib' (no such file)
cannot load library 'libcairo-2.dll': dlopen(libcairo-2.dll, 0x0002): tried: 'libcairo-2.dll' (no such file), '/usr/local/lib/libcairo-2.dll' (no such file), '/usr/lib/libcairo-2.dll' (no such file), '/Users/jordan/Documents/new_project/libcairo-2.dll' (no such file), '/usr/local/lib/libcairo-2.dll' (no such file), '/usr/lib/libcairo-2.dll' (no such file)
liZe commented 2 years ago

It's definitely installed as I can see the libs in "/opt/homebrew/lib. Just not sure how to get python to see it without adding an icky dyld.DEFAULT_LIBRARY_FALLBACK line before import. Doesn't seem specifically a cairosvg problem though.

Then you’ll have to ask the Hombrew devs how you can use pyenv with Homebrew’s libraries.

sinwoobang commented 2 years ago

If nothing helped you, try this workaround. On your project root; where import cairosvg

sudo ln -s /opt/homebrew/lib/libcairo* .

This is a way to create symbolic links locally.

IshanKumar22 commented 1 year ago

Same problem. Running normal installation of python (3.11.0) and pip (22.3.1).

ndrezn commented 1 year ago

I'm also running into this issue -- the tip from @sinwoobang solved it for me after other recommendations failed. It seems plausible this is a Homebrew issue and not a CairoSVG issue so I understand why this issue is closed but it'd be great if this error was documented somewhere and a consistent workaround provided. I imagine many users with Apple silicon are running into this error.

liZe commented 1 year ago

I imagine many users with Apple silicon are running into this error.

We don’t own a Apple computer, so we can’t test anything. If anyone is interested in providing a reliable workaround (and answering the people that will get the bug, even with the workaround), your help is welcome!

varalgit commented 1 year ago

The tip from @sinwoobang solved it for me too after I tried all the other suggestions on this page, which did not work. Thanks @sinwoobang!!

rcthakuri commented 1 year ago

I was facing similar issue in Mac M2, and resolved by installing the cairo using Rosseta. Solution:

  1. Open application > go to Utilities > right click terminal and checked Open using Rosseta
  2. Now open terminal
  3. And run brew install cairo

Note: Make sure to run your application from terminal enabled with Rosseta, running it through IDE & editor may require further setup.

385