nbconvert 5.6.1 failed with message: "nbconvert failed: Inkscape svg to pdf conversion failed" in Win 10

Created on 15 Jul 2020  路  10Comments  路  Source: jupyter/nbconvert


This happens when trying to convert a notebook with svg graphics embedded.

I have a hunch that the svg2pdf.py code can not handle a blank in the program name of inkscape as it is the case on my machine ("C:\Program Files\Inkscape\bin\inkscape.exe"). Also the text before the exception "'C:\Program' is not recognized as an internal or external command, operable program or batch file." gives this impression.

Environment

  • Windows 10 English
  • Inkscape 1.0


Steps to reproduce

  • generate output with SVG graphics (e.g. with display(SVG(filename='test.svg'))
  • try to export it to PDF (download as pdf via latex)


(Rather) minimal notebook: Gantt_Minimal_SVG.txt


Nbconvert version: 5.6.1

bug good first issue help wanted

Most helpful comment

I did a little research with the svg2pdf.py of the above mentioned alpha and found the following:

My registry contains the string value "C:\Program Files\Inkscape\bin\inkscape.exe,0" (without quotation marks). When you enter that text in a command line prompt, the trailing ",0" leads to

'"C:\Program Files\Inkscape\bin\inkscape.exe,0"' is not recognized as an internal or external command, operable program or batch file."

Second, the blank in "Program Files" causes problems.

If I modify svg2pdf.py to remove the ",0" when getting the string from the registry, e.g., by

inkscape = winreg.QueryValueEx(rkey, "")[0].split(',')[0]

and change the command string from

      return '{inkscape}{gui_option}{export_option}='.format(
            inkscape=self.inkscape, export_option=export_option, gui_option=gui_option
        ) + '"{to_filename}" "{from_filename}"'

to

      return '"{inkscape}"{gui_option}{export_option}='.format(
            inkscape=self.inkscape, export_option=export_option, gui_option=gui_option
        ) + '"{to_filename}" "{from_filename}"'

, then svg conversion with inkscape works for me.

As I don't know if these changes will work for all OS (and not only for my Win10), I'll leave it here for someone to pick it up, include it, and test it properly.

All 10 comments

The alpha for nbconvert -- 6.0.0a4 -- should fix the issue with inkscape 1.0 on windows, if you want to give that a try.

Thanks. I've upgraded an anaconda env to nbconvert 6.0.0.a4. After that I've got this error message when trying to export to pdf:

[E 08:02:48.932 NotebookApp] nbconvert failed: [WinError 2] The system cannot find the file specified
    Traceback (most recent call last):
      File "...anaconda env...\lib\site-packages\traitlets\traitlets.py", line 528, in get
        value = obj._trait_values[self.name]
    KeyError: 'command'

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "...anaconda env...\lib\site-packages\traitlets\traitlets.py", line 528, in get
        value = obj._trait_values[self.name]
    KeyError: 'inkscape_version'

    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "...anaconda env...\lib\site-packages\notebook\nbconvert\handlers.py", line 132, in get
        resources=resource_dict
      File "...anaconda env...\lib\site-packages\nbconvert\exporters\pdf.py", line 176, in from_notebook_node
        nb, resources=resources, **kw
      File "...anaconda env...\lib\site-packages\nbconvert\exporters\latex.py", line 77, in from_notebook_node
        return super().from_notebook_node(nb, resources, **kw)
      File "...anaconda env...\lib\site-packages\nbconvert\exporters\templateexporter.py", line 340, in from_notebook_node
        nb_copy, resources = super().from_notebook_node(nb, resources, **kw)
      File "...anaconda env...\lib\site-packages\nbconvert\exporters\exporter.py", line 143, in from_notebook_node
        nb_copy, resources = self._preprocess(nb_copy, resources)
      File "...anaconda env...\lib\site-packages\nbconvert\exporters\exporter.py", line 320, in _preprocess
        nbc, resc = preprocessor(nbc, resc)
      File "...anaconda env...\lib\site-packages\nbconvert\preprocessors\base.py", line 47, in __call__
        return self.preprocess(nb, resources)
      File "...anaconda env...\lib\site-packages\nbconvert\preprocessors\base.py", line 69, in preprocess
        nb.cells[index], resources = self.preprocess_cell(cell, resources, index)
      File "...anaconda env...\lib\site-packages\nbconvert\preprocessors\convertfigures.py", line 46, in preprocess_cell
        self.from_format, output.data[self.from_format])
      File "...anaconda env...\lib\site-packages\nbconvert\preprocessors\svg2pdf.py", line 126, in convert_figure
        shell = self.command.format(from_filename=input_filename,
      File "...anaconda env...\lib\site-packages\traitlets\traitlets.py", line 556, in __get__
        return self.get(obj, cls)
      File "...anaconda env...\lib\site-packages\traitlets\traitlets.py", line 535, in get
        value = self._validate(obj, dynamic_default())
      File "...anaconda env...\lib\site-packages\nbconvert\preprocessors\svg2pdf.py", line 78, in _command_default
        major_verison = self.inkscape_version.split('.')[0]
      File "...anaconda env...\lib\site-packages\traitlets\traitlets.py", line 556, in __get__
        return self.get(obj, cls)
      File "...anaconda env...\lib\site-packages\traitlets\traitlets.py", line 535, in get
        value = self._validate(obj, dynamic_default())
      File "...anaconda env...\lib\site-packages\nbconvert\preprocessors\svg2pdf.py", line 60, in _inkscape_version_default
        stderr=subprocess.PIPE)
      File "...anaconda env...\lib\subprocess.py", line 800, in __init__
        restore_signals, start_new_session)
      File "...anaconda env...\lib\subprocess.py", line 1207, in _execute_child
        startupinfo)
    FileNotFoundError: [WinError 2] The system cannot find the file specified
[W 08:02:48.939 NotebookApp] 500 GET /nbconvert/pdf/Gantt_Spielereien/Gantt_Minimal_SVG.ipynb?download=true (::1): nbconvert failed: [WinError 2] The system cannot find the file specified

btw, exporting to pdf without SVG works in this environment.

I did a little research with the svg2pdf.py of the above mentioned alpha and found the following:

My registry contains the string value "C:\Program Files\Inkscape\bin\inkscape.exe,0" (without quotation marks). When you enter that text in a command line prompt, the trailing ",0" leads to

'"C:\Program Files\Inkscape\bin\inkscape.exe,0"' is not recognized as an internal or external command, operable program or batch file."

Second, the blank in "Program Files" causes problems.

If I modify svg2pdf.py to remove the ",0" when getting the string from the registry, e.g., by

inkscape = winreg.QueryValueEx(rkey, "")[0].split(',')[0]

and change the command string from

      return '{inkscape}{gui_option}{export_option}='.format(
            inkscape=self.inkscape, export_option=export_option, gui_option=gui_option
        ) + '"{to_filename}" "{from_filename}"'

to

      return '"{inkscape}"{gui_option}{export_option}='.format(
            inkscape=self.inkscape, export_option=export_option, gui_option=gui_option
        ) + '"{to_filename}" "{from_filename}"'

, then svg conversion with inkscape works for me.

As I don't know if these changes will work for all OS (and not only for my Win10), I'll leave it here for someone to pick it up, include it, and test it properly.

@MSeal theoky was quicker. :)
I had the exact same problem on Win10 and 6.0.0.a4, with the message: nbconvert failed: Inkscape svg to pdf conversion failed
The server showed an exception, something like: 'C:\Program' is not recognized as a command.
Quick solution for beginners: reinstall Inkscape in a path with no whitespace.

Ahh thanks for finding the existing issue :+1:

I've been swamped and my free time has been limited so I'm not sure when I'll get to this. Would love to have a new contributor try to put this into a PR with a test improvement.

I did a little research with the svg2pdf.py of the above mentioned alpha and found the following:

My registry contains the string value "C:\Program Files\Inkscape\bin\inkscape.exe,0" (without quotation marks). When you enter that text in a command line prompt, the trailing ",0" leads to

'"C:\Program Files\Inkscape\bin\inkscape.exe,0"' is not recognized as an internal or external command, operable program or batch file."

Second, the blank in "Program Files" causes problems.

If I modify svg2pdf.py to remove the ",0" when getting the string from the registry, e.g., by

inkscape = winreg.QueryValueEx(rkey, "")[0].split(',')[0]

and change the command string from

      return '{inkscape}{gui_option}{export_option}='.format(
            inkscape=self.inkscape, export_option=export_option, gui_option=gui_option
        ) + '"{to_filename}" "{from_filename}"'

to

      return '"{inkscape}"{gui_option}{export_option}='.format(
            inkscape=self.inkscape, export_option=export_option, gui_option=gui_option
        ) + '"{to_filename}" "{from_filename}"'

, then svg conversion with inkscape works for me.

As I don't know if these changes will work for all OS (and not only for my Win10), I'll leave it here for someone to pick it up, include it, and test it properly.

Hi @theoky, I'm trying to follow your solution. Could you please explain how to locate the file svg2pdf.py?

Hi @theoky, I'm trying to follow your solution. Could you please explain how to locate the file svg2pdf.py?

I can find it on my machine here:

  • \
  • \

Hope that helps.

Hi @theoky, I'm trying to follow your solution. Could you please explain how to locate the file svg2pdf.py?

I can find it on my machine here:

  • \python-3.#.#.amd64\Lib\site-packages\nbconvert\preprocessors
  • \\Lib\site-packages\nbconvert\preprocessors

Hope that helps.

Thank you so much. I've just found it. It's sad that the content of the file is changed and I'm unable to apply your method.

"""Module containing a preprocessor that converts outputs in the notebook from 
one format to another.
"""

# Copyright (c) Jupyter Development Team.
# Distributed under the terms of the Modified BSD License.

import base64
import io
import os
import sys
import subprocess

from ipython_genutils.py3compat import cast_unicode_py2
from testpath.tempdir import TemporaryDirectory
from traitlets import Unicode, default

from .convertfigures import ConvertFiguresPreprocessor

if sys.version_info >= (3,3):
    from shutil import which
    get_inkscape_path = which('inkscape')
else:
    get_inkscape_path = None


INKSCAPE_APP = '/Applications/Inkscape.app/Contents/Resources/bin/inkscape'

if sys.platform == "win32":
    try:
        import winreg
    except ImportError:
        import _winreg as winreg


class SVG2PDFPreprocessor(ConvertFiguresPreprocessor):
    """
    Converts all of the outputs in a notebook from SVG to PDF.
    """

    @default('from_format')
    def _from_format_default(self):
        return 'image/svg+xml'

    @default('to_format')
    def _to_format_default(self):
        return 'application/pdf'

    command = Unicode(
        help="""The command to use for converting SVG to PDF

        This string is a template, which will be formatted with the keys
        to_filename and from_filename.

        The conversion call must read the SVG from {from_filename},
        and write a PDF to {to_filename}.
        """).tag(config=True)

    @default('command')
    def _command_default(self):
        return self.inkscape + \
               ' --without-gui --export-pdf="{to_filename}" "{from_filename}"'

    inkscape = Unicode(help="The path to Inkscape, if necessary").tag(config=True)
    @default('inkscape')
    def _inkscape_default(self):
        if get_inkscape_path is not None:
            return get_inkscape_path 
        if sys.platform == "darwin":
            if os.path.isfile(INKSCAPE_APP):
                return INKSCAPE_APP
        if sys.platform == "win32":
            wr_handle = winreg.ConnectRegistry(None, winreg.HKEY_LOCAL_MACHINE)
            try:
                rkey = winreg.OpenKey(wr_handle, "SOFTWARE\\Classes\\inkscape.svg\\DefaultIcon")
                inkscape = winreg.QueryValueEx(rkey, "")[0]
            except FileNotFoundError:
                raise FileNotFoundError("Inkscape executable not found")
            return inkscape
        return "inkscape"


    def convert_figure(self, data_format, data):
        """
        Convert a single SVG figure to PDF.  Returns converted data.
        """

        #Work in a temporary directory
        with TemporaryDirectory() as tmpdir:

            #Write fig to temp file
            input_filename = os.path.join(tmpdir, 'figure.svg')
            # SVG data is unicode text
            with io.open(input_filename, 'w', encoding='utf8') as f:
                f.write(cast_unicode_py2(data))

            #Call conversion application
            output_filename = os.path.join(tmpdir, 'figure.pdf')
            shell = self.command.format(from_filename=input_filename, 
                                   to_filename=output_filename)
            subprocess.call(shell, shell=True) #Shell=True okay since input is trusted.

            #Read output from drive
            # return value expects a filename
            if os.path.isfile(output_filename):
                with open(output_filename, 'rb') as f:
                    # PDF is a nb supported binary, data type, so base64 encode.
                    return base64.encodestring(f.read())
            else:
                raise TypeError("Inkscape svg to pdf conversion failed")

I stumbled on the same issued and found #244. I created the pull request #1469 for this.

I created the pull request #1469 for this.

Thanks for creating the pull request.

Was this page helpful?
0 / 5 - 0 ratings