LaTeX rendering in Inkscape and Python 3.4

Asked by Natalia

I need to insert a LaTeX formula into my picture. To achieve this, I do Extensions --> Render --> LaTeX... In the appeared window I type $a + b = c$ and press Apply. A window with message "'LaTeX' working, please wait..." appears. Then, the second window with message about error arises. The message is the following:

Traceback (most recent call last):
  File "eqtexsvg.py", line 160, in <module>
    e.affect()
  File "/usr/local/share/inkscape/extensions/inkex.py", line 285, in affect
    self.output()
  File "/usr/local/share/inkscape/extensions/inkex.py", line 272, in output
    self.document.write(sys.stdout)
  File "src/lxml/lxml.etree.pyx", line 2033, in lxml.etree._ElementTree.write (src/lxml/lxml.etree.c:65098)
  File "src/lxml/serializer.pxi", line 726, in lxml.etree._tofilelike (src/lxml/lxml.etree.c:138907)
  File "src/lxml/lxml.etree.pyx", line 324, in lxml.etree._ExceptionContext._raise_if_stored (src/lxml/lxml.etree.c:12081)
  File "src/lxml/serializer.pxi", line 643, in lxml.etree._FilelikeWriter.write (src/lxml/lxml.etree.c:137523)
TypeError: must be str, not bytes

I have changed
self.document.write(sys.stdout)
to
self.document.write(str(sys.stdout))
in the 272-th line of inkex.py, but after this the following error is obtained,

Traceback (most recent call last):
  File "eqtexsvg.py", line 160, in <module>
    e.affect()
  File "/usr/local/share/inkscape/extensions/inkex.py", line 285, in affect
    self.output()
  File "/usr/local/share/inkscape/extensions/inkex.py", line 272, in output
    self.document.write(str(sys.stdout))
  File "src/lxml/lxml.etree.pyx", line 2033, in lxml.etree._ElementTree.write (src/lxml/lxml.etree.c:65098)
  File "src/lxml/serializer.pxi", line 714, in lxml.etree._tofilelike (src/lxml/lxml.etree.c:138800)
  File "src/lxml/serializer.pxi", line 773, in lxml.etree._create_output_buffer (src/lxml/lxml.etree.c:139464)
  File "src/lxml/serializer.pxi", line 762, in lxml.etree._create_output_buffer (src/lxml/lxml.etree.c:139264)
PermissionError: [Errno 13] Permission denied

I don't know what to do with this error, I don't have a lot of experience in Python.

My system information:
# lsb_release -idrc && echo Kernel Release: `uname -r`
Distributor ID: SUSE LINUX
Description: openSUSE Leap 42.1 (x86_64)
Release: 42.1
Codename: n/a
Kernel Release: 4.1.36-44-default

# inkscape --version
Inkscape 0.92.1pre1 r15355

# python --version
Python 3.4.5

Is this something wrong in Inkscape or should I fix something at my system?

Thank you in advance.
Regards, Natalia

Before installation of Inkscape 0.92 I used Inkscape 0.91. It worked perfectly with Python 2.7. Then I needed update Python to version 3.4. After this update LaTeX in Inkscape stopped to work. Error messages told about wrong syntax. I fixed some errors and arrived to the same errors as I have already described for 0.92-th version of Inkscape.

Question information

Language:
English Edit question
Status:
Invalid
For:
Inkscape Edit question
Assignee:
No assignee Edit question
Solved by:
johnc
Solved:
Last query:
Last reply:
Revision history for this message
Hachmann (marenhachmann) said :
#1

Hi Natalia,

this question at stackoverflow contains a possible answer, if you want to adapt the extensions to run with python3:
http://stackoverflow.com/questions/21689365/python-3-typeerror-must-be-str-not-bytes-with-sys-stdout-write

I'm not sure if all extensions are actually python 3 compatible, so this change may entrail further work.

So what I would try is this (in inkex.py) if you want to keep python3 as the default for the system:

replace
#!/usr/bin/env python

by

#!/usr/bin/env python2

(and make sure that you have python2.7 installed)

Kind Regards,
 Maren

Revision history for this message
Natalia (natasha.from.dnepropetrovsk) said :
#2

Hi, Maren,

Thank you for the reply.

Tries to use decode lead to the error:

self.document.write((sys.stdout).decode('utf-8'))
AttributeError: '_io.TextIOWrapper' object has no attribute 'decode'

I have tried to replace
#!/usr/bin/env python
by
#!/usr/bin/env python2
as in inkex.py or in all *.py files. This doesn't help. The same error (mentioned in the first post) is obtained.

# ls -l /usr/bin | grep 'python'
lrwxrwxrwx 1 root root 7 Фев 5 17:25 python -> python3
lrwxrwxrwx 1 root root 9 Июл 27 2016 python2 -> python2.7
-rwxr-xr-x 1 root root 6296 Июл 19 2016 python2.7
-rwxr-xr-x 1 root root 1681 Июл 19 2016 python2.7-config
lrwxrwxrwx 1 root root 16 Июл 27 2016 python2-config -> python2.7-config
lrwxrwxrwx 1 root root 9 Авг 19 21:12 python3 -> python3.4
-rwxr-xr-x 2 root root 10504 Авг 12 10:51 python3.4
-rwxr-xr-x 2 root root 10504 Авг 12 10:51 python3.4m
lrwxrwxrwx 1 root root 14 Июл 27 2016 python-config -> python2-config

As only I relinked python to python2 LaTeX in Inkscape works. But I need the python link pointing on python3.

Regards, Natalia

Revision history for this message
Hachmann (marenhachmann) said :
#3

Can you print which python version is used when you're running the extension, Natalia?

import sys

inkex.debug(sys.version_info)

Revision history for this message
Natalia (natasha.from.dnepropetrovsk) said :
#4

Hi, Maren!

If I understand you correctly,

> cd /usr/local/share/inkscape/extensions/
> grep 'env\ python' inkex.py
#!/usr/bin/env python2
> python
Python 3.4.5 (default, Jul 03 2016, 13:32:18) [GCC] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import inkex
>>> import sys
>>> inkex.debug(sys.version_info)
sys.version_info(major=3, minor=4, micro=5, releaselevel='final', serial=0)
sys.version_info(major=3, minor=4, micro=5, releaselevel='final', serial=0)

Revision history for this message
Hachmann (marenhachmann) said :
#5

Hi Natalia,

so it doesn't respect the python version given in the file header, but just loads the system's python version (probably done even before the file is read...)

How about starting Inkscape with a different python environment variable?

So, you could try to start Inkscape via command line like this (not tested, you need to adapt to your python paths, or maybe you can even load the path from a whereis or something - sorry, not a command line guru...) :

export PYTHONPATH=/path/to/python2
inkscape

(I've made myself a little desktop starter that sets an environment variable (different one). Let me know if this would be useful for you)

Kind Regards,
 Maren

Revision history for this message
Hachmann (marenhachmann) said :
#6

Ah, or maybe we misunderstood each other.

I meant to run the extension from Inkscape, making sure that in every file that is needed, python2 is set in the header.

So, for your Latex extension, you'd need to insert the python2 header into inkex.py and into all .py files that belong to the latex thing.

Then insert the debug line either into inkex.py or into the extension (or better, into both, for testing).
May give the same result as your test, but it would be good to know for sure.

Revision history for this message
Natalia (natasha.from.dnepropetrovsk) said :
#7

Hi again!

I have set
#!/usr/bin/env python2
in all .py files of /usr/local/share/inkscape/extensions/ directory and added
print(sys.version_info)
into inkex.py:

. . .
import copy
import gettext
import optparse
import os
import random
import re
import sys
from math import *

print(sys.version_info)
. . .

Then I have run Inkscape from command line and tried to input Latex formula. It showed the abovementioned error message. When I tried to close window with message, Inkscape was closed... The command line output:

> inkscape

(inkscape:15393): Gtk-WARNING **: Theme directory actions/48 of theme breeze has no size field

(inkscape:15393): Gtk-WARNING **: Theme directory categories/16 of theme breeze has no size field

(inkscape:15393): Gtk-WARNING **: Theme directory categories/22 of theme breeze has no size field

(inkscape:15393): Gtk-WARNING **: Theme directory categories/48 of theme breeze has no size field

(inkscape:15393): Gtk-WARNING **: Theme directory devices/48 of theme breeze has no size field

(inkscape:15393): Gtk-WARNING **: Theme directory of theme oxygen has no size field

FontLister::get_best_style_match(): can't find family: Sans
/tmp/ink_ext_XXXXXX.svgILTFVY:1: parser error : Start tag expected, '<' not found
sys.version_info(major=3, minor=4, micro=5, releaselevel='final', serial=0)
^

(inkscape:15393): glibmm-ERROR **:
unhandled exception (type std::exception) in signal handler:
what: Open failed

Trace/breakpoint trap

I haven't try a trick with environment variables yet. Probably, it shouldn't be exactly as you wrote, since both python3 and python2 are in the same directory /usr/bin/ in my case...

Revision history for this message
Hachmann (marenhachmann) said :
#8

Okay, so we now know for sure that it's using the 3.4.5 python no matter what the extension files say.

It seems somehow the debug output ended up in the temporary file that is created by the Inkscape extension.
The crash error should be gone when you remove the inkex.debug(...) thing.

Hopefully, the environment variable trick will work - crossing my fingers!

Kind Regards,
 Maren

Revision history for this message
Natalia (natasha.from.dnepropetrovsk) said :
#9

Hi Maren!

Seems, the reason of usage of 3-rd Python instead of second, is calls of functions of .py-files from .inx-files through

<command reldir="extensions" interpreter="python">eqtexsvg.py</command>

I have tried to change interpreter="python" to interpreter="python2" in eqtexsvg.inx, but then eqtexsvg.py isn't called and the following error message is written in command line (I run Inkscape from command line now):

Can't Spawn!!! spawn returns: Failed to execute child process "" (No such file or directory)

To test this, I have written file switchPyEqtexsvg.py;

> cat switchPyEqtexsvg.py
#!/usr/bin/env python

import subprocess as spc
print(spc.getoutput("python2 eqtexsvg.py"))

which explicitly runs .py script with python2, and changed the abovementioned line in the eqtexsvg.inx file to

<!-- <command reldir="extensions" interpreter="python">eqtexsvg.py</command>-->
<command reldir="extensions" interpreter="python">switchPyEqtexsvg.py</command>

Thus, I obtain

>>>>> eqtexsvg.py >>>sys.version_info(major=2, minor=7, micro=12, releaselevel='

from eqtexsvg.py and from inkex.py also. But even if I remove output of sys.version_info from .py files, Inkscape fails when I try to generate a Latex formula typed in the 'LaTeX...' subwindow. Probably, the mediated call of eqtexsvg.py isn't provided.

Do you know, how to explain .inx file that .py files should be run with python2 instead of python?

Regards,
Natalia

Revision history for this message
Hachmann (marenhachmann) said :
#10

Hi Natalia,

did you try setting the environment variable or alias yet? Currently, I think this is the most promising route.
See http://stackoverflow.com/questions/19256127/two-versions-of-python-on-linux-how-to-make-2-7-the-default

Then the next thing I would try would be to setup a virtualenv with python 2.7, and start Inkscape from inside the activated virtualenv. (if you've never heard about virtualenv, this sounds complex, but the commands are actually very easy:

# setup virtual environment for python 2.7
$ virtualenv pythonenv -p /usr/bin/python2.7

$ cd pythonenv

# activate the environment, from now on it will be used for everything you start here
$ source ./bin activate

# lxml needs to be installed, maybe also other things
$ pip install lxml

# start Inkscape from within the pythonenv
$ inkscape

If this doesn't work, then I fear I'm at my wit's end :-/

Kind Regards,
 Maren

Revision history for this message
Natalia (natasha.from.dnepropetrovsk) said :
#11

Hi, Maren,

Seems, setting the env. variable doesn't help:

> export PYTHONPATH=/usr/bin/python2.7
> echo $PYTHONPATH
/usr/bin/python2.7
> inkscape

(inkscape:7227): Gtk-WARNING **: Theme directory actions/48 of theme breeze has no size field

(inkscape:7227): Gtk-WARNING **: Theme directory categories/16 of theme breeze has no size field

(inkscape:7227): Gtk-WARNING **: Theme directory categories/22 of theme breeze has no size field

(inkscape:7227): Gtk-WARNING **: Theme directory categories/48 of theme breeze has no size field

(inkscape:7227): Gtk-WARNING **: Theme directory devices/48 of theme breeze has no size field

(inkscape:7227): Gtk-WARNING **: Theme directory of theme oxygen has no size field

FontLister::get_best_style_match(): can't find family: Sans
/tmp/ink_ext_XXXXXX.svgPITTVY:1: parser error : Start tag expected, '<' not found
>>>>> eqtexsvg.py >>>sys.version_info(major=3, minor=4, micro=5, releaselevel='f
^

(inkscape:7227): glibmm-ERROR **:
unhandled exception (type std::exception) in signal handler:
what: Open failed

Trace/breakpoint trap

Or am I doing anything wrong?

Regards,
Natalia

Revision history for this message
Hachmann (marenhachmann) said :
#12

You need to remove the debug output, it breaks the output to stdout.

Does this make a difference?

Revision history for this message
Hachmann (marenhachmann) said :
#13

For checking which python version will be used,

$ which python

will give you a good result.

Revision history for this message
Natalia (natasha.from.dnepropetrovsk) said :
#14

Hi, Maren!

Removing of print('>>>>> eqtexsvg.py >>>' + str(sys.version_info)) line doesn't help:

> export PYTHONPATH=/usr/bin/python2.7
> which python
/usr/bin/python
> ls -l /usr/bin/ | grep 'python '
lrwxrwxrwx 1 root root 7 Фев 11 21:40 python -> python3
> inkscape

When I try to produce a LaTeX formula, Inkscape returns the error message, written in the first post. In the command line the warnings, listed in the post #7, are written.

Regards,
Natalia

Revision history for this message
Hachmann (marenhachmann) said :
#15

That removal was only meant to silence the error message that you described in comment #11.

Did you try the virtualenv solution yet?

Kind Regards,
 Maren

Revision history for this message
Natalia (natasha.from.dnepropetrovsk) said :
#17

Hi, Maren!

Sorry, I couldn't answer earlier.

Yes, run Inkscape through virtualenv does help. Just one remark:
> source ./bin/activate
should be done instead of
> source ./bin activate
at least at my system.

Thank you.
However, this is not the most convenient method to use Inkscape...
Probably, some script for this should be written, and it should be somehow explained to system that it has run this script instead of directly Inkscape...

I think, in my case I will better set /usr/bin/python linking python2.7 and explicitly set python3 where I need it.

Thank you again for your help.
Regards, Natalia

Revision history for this message
Hachmann (marenhachmann) said :
#18

Hi Natalia,

good to see you again! :D

You're on Linux Mint, right? It's quick to script this:

You could create a desktop starter that does it for you, then you'd just need to double-click on it to start your Inkscape via virtualenv (if you want to keep your Python3).

The starter could contain a command like this:
konsole -e my_inkscapestartscript.sh

(if you've got konsole installed, else you'd need to use the command for another terminal application)

and the script file "my_inkscapestartscript.sh" could be:

cd /my/virtualenv/directory
source ./bin/activate
inkscape

Regards,
 Maren

Revision history for this message
su_v (suv-lp) said :
#19

Just a hint on how to set a custom version of the python interpreter per Inkscape user preferences:
https://answers.launchpad.net/inkscape/+question/215655#comment-2

Revision history for this message
Natalia (natasha.from.dnepropetrovsk) said :
#20

Good afternoon!

@su_v Thank you! It has helped!

@Maren
Thank you for tries to help me! I use not Mint, but openSUSE and advice by su_v has helped me. Anyway, thank you very much!

Inkscape does insert LaTeX expressions;

> ls -l /usr/bin/ | grep 'python'
lrwxrwxrwx 1 root root 7 Мар 13 14:21 python -> python3
lrwxrwxrwx 1 root root 9 Июл 27 2016 python2 -> python2.7
-rwxr-xr-x 1 root root 6296 Июл 19 2016 python2.7
-rwxr-xr-x 1 root root 1681 Июл 19 2016 python2.7-config
lrwxrwxrwx 1 root root 16 Июл 27 2016 python2-config -> python2.7-config
lrwxrwxrwx 1 root root 9 Авг 19 2016 python3 -> python3.4
-rwxr-xr-x 2 root root 10504 Авг 12 2016 python3.4
-rwxr-xr-x 2 root root 10504 Авг 12 2016 python3.4m
lrwxrwxrwx 1 root root 14 Июл 27 2016 python-config -> python2-config
> inkscape #with abovementioned changes in /usr/local/share/inkscape/extensions/inkex.py and call Extensions --> Render --> LaTeX...

(inkscape:2458): Gtk-WARNING **: Theme directory actions/48 of theme breeze has no size field

(inkscape:2458): Gtk-WARNING **: Theme directory categories/16 of theme breeze has no size field

(inkscape:2458): Gtk-WARNING **: Theme directory categories/22 of theme breeze has no size field

(inkscape:2458): Gtk-WARNING **: Theme directory categories/48 of theme breeze has no size field

(inkscape:2458): Gtk-WARNING **: Theme directory devices/48 of theme breeze has no size field

(inkscape:2458): Gtk-WARNING **: Theme directory of theme oxygen has no size field

FontLister::get_best_style_match(): can't find family: Sans
/tmp/ink_ext_XXXXXX.svgLRJDXY:1: parser error : Start tag expected, '<' not found
sys.version_info(major=2, minor=7, micro=12, releaselevel='final', serial=0)
^

(inkscape:2458): glibmm-ERROR **:
unhandled exception (type std::exception) in signal handler:
what: Open failed

Trace/breakpoint trap

Regards, Natalia

Revision history for this message
Hachmann (marenhachmann) said :
#21

Hi Natalia,

please remove all the debug output that we have inserted during our trials.
The error you get seems to be due to the debug output being accidentally inserted into the temporary SVG file.

Regards,
 Maren

@su_v: Thank you!!! (and wow, that is really a well-hidden feature - what do you think would be the best place to document this? Or is it already documented anywhere else?)

Revision history for this message
su_v (suv-lp) said :
#22

On 2017-03-15 14:33 (+0100), Hachmann wrote:
> @su_v: Thank you!!! (and wow, that is really a well-hidden feature -
> what do you think would be the best place to document this? Or is it
> already documented anywhere else?)

AFAICT the code/feature was initially added in 2005, so I'd be a bit
surprised if it's only documented in the source code (but I don't recall
where I had picked it up myself back in 2012, when answering the other
question, nor did I manage to find any documentation today (apart from a
few mentions in the archive of the mailing lists, mostly en passant)):

$ bzr log -r 6697
------------------------------------------------------------
revno: 6697
committer: gouldtj
timestamp: Tue 2005-05-10 06:18:29 +0000
message:
  Submitting a bug fix for Aaron. Also adding in code for grabbing the
  interpreter from the preferences.
$
$ bzr diffstat -c 6697
 src/extension/implementation/script.cpp | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)
$

Branch repository:
https://code.launchpad.net/~vcs-imports/inkscape/old-main
(diff not available via lp web interface)

Current code (trunk):
Table with supported interpreters:
https://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/view/15598/src/extension/implementation/script.cpp

Lookup in prefs:
https://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/view/15598/src/extension/implementation/script.cpp

Revision history for this message
su_v (suv-lp) said :
#23

@Hachmann - sorry, I messed up earlier with copy&paste. Here are the correct links to current code lines:

Table with supported interpreters:
https://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/view/head:/src/extension/implementation/script.cpp#L79

Lookup in prefs:
https://bazaar.launchpad.net/~inkscape.dev/inkscape/trunk/view/head:/src/extension/implementation/script.cpp#L121

Revision history for this message
Hachmann (marenhachmann) said :
#24

Cool, thank you, @su_v!

It's not exactly a *frequently* asked question, but I guess it'll become more frequent with the switch to python3 as default python on various Linux systems.... Otoh, extensions have been made compatible by the recent 2to3 addition. Don't know where to put the info...

It's not for developers, but for ordinary users, so the extension development page doesn't make sense. Wish we had an editable manual...

Do you have any ideas? It would be a pity if this were only documented inside your and my head...

Revision history for this message
su_v (suv-lp) said :
#25

On 2017-03-15 23:13 (+0100), Hachmann wrote:
> Otoh, extensions have been made compatible by the recent 2to3
> addition.

Extensions in current stable and current trunk do NOT support Python 3
yet. I haven't tested Oskay's diff (or now branch - likely you refer to
that), but I do recall from my own attempts a year ago that more changes
were required than those provided in that diff/branch for the
python-based script extensions distributed with Inkscape. AFAICT the
merge proposal has neither been reviewed yet, nor thoroughly tested at
this point in time.

> Don't know where to put the info...
>
> It's not for developers, but for ordinary users, so the extension
> development page doesn't make sense. Wish we had an editable manual...
>
> Do you have any ideas?

You don't really want to know my thoughts or opinion on that.

Anyway, here's a condensed version: for now, I probably would recommend
a wiki page tracking the implementation of Python 2 / 3 compatibility,
and ultimately the migration to Python 3, similarly to pages that e.g.
tracked information about the migration from GTK2 to GTK3 (with a period
where both versions were supported), or other topics like mesh
gradients, or canvas rotation. I'd also check the wiki's 'Extensions'
category for any pages where this specific preferences setting could be
added in a foot-note.

But: given the planned obsolescence of the current wiki, that's of
course a short-lived proposal, and neither of the two planned successors
for the wiki will be an ideal place for such information (the details
are both technical in nature and geared towards more advanced users and
Inkscape users on Linux where the default version of Python is beyond
the control of Inkscape - advising for example regular or casual
Inkscape users on Windows (or macOS) to manually add a specific value to
the preferences file for which there is no GUI will only set them up for
frustrating failures once the project ships binary packages of a future
release with a different python version configured (macOS) and/or
bundled (Windows). It's rather easy to forget about manual edits once
applied to the prefs file).

This discussion is getting off-topic for the specific question asked
here though (#451483), sorry for that.

Revision history for this message
Hachmann (marenhachmann) said :
#26

<offtopic>
@su_v: Thank you for your reply. I wouldn't have asked if I wouldn't have wanted to read it! Our opinions do have weight, even if it's sometimes impossible to accomodate for them, unless we ourselves actively look for a way to make it possible. When we can't, or don't, it won't happen - then those who can, or do, will implement what seems best to them (and they will be have to take on responsibility for it). I know I can't build or host or administer a Wiki machine, and I don't have the energy to go against people and push a call for help to social media - so I'll have to live with what will happen.

It makes sense to add it to the Wiki, thank you for that suggestion.

For Windows, the Python version the extensions will run with is included, so regular users will hopefully have no need to change it.
So, as far as I understand, this is mostly relevant for cases like Natalia's here (I have no idea about the macOS situation).

Thank you again,
 Maren

</offtopic>