Python в Latex
Использовать Python в LaTeX было бы очень удобно. Сразу предупреждаю, что предложенные методы считаются небезопасными, потому-что Python умеет гадить, если написать соответствующий код, так что проверяйте его (=
Существует готовый метод в виде файла стилей, используется так:
\usepackage{python}
\begin{python}
from math import sin
a = sin(5)
c = sin(9)
b = max(a,c)
print b
\end{python}
Этот пакет, фактически, создает jobname.py, пишет вывод в jobname.py.out, jobname.py.err, и читает его. Метод плох тем, что переменные не сохраняются от кода к коду, и для этого приходится использовать pickle, приходиться каждый раз заново всё import`ить и т.п., а еще мне кажется, что удобно иметь все расчеты в одном месте в отдельном файле, поэтому я построил свой лунапарк...
Всё очень просто. Добавляем в преамбулу следующее:
\newcommand{\python}[1]{%
\immediate\write18{python #1 > ./py.out 2> ./py.err}
\immediate\input"py.out"}
\newcommand{\ptn}[1]{%
\python{./path_to_your_scripts/script_name.py #1}}
\newcommand{\peval}[1]{%
\python{-c "print #1" |./path_to_your_scripts/sedder}}
\newcommand{\comments}[1]{}
Первый макрос вызывает python с заданными вами аргументами, второй запускает конкртеный скрипт с аргументами, ну а третий может выполнять однострочный код Пайтона, который потом преаброзовывается маленьким sed`ом, что бы заменить точки на запятые. И пооследний макрос добавил, что бы при выводе Python и появлении каких-то ошибок в Latex было понятно где проблема
В скрипте у меня есть маленькое ухищрение для красивого вывода(правда исключительно для математического окружения), ну и седом тоже могу поделиться(естественно sed будет работать только если он у вас есть).
sedder:
#!/bin/sh sed -e 's/\./,/'Сделайте его исполняемым.
конец файла "./path_to_your_scripts/script_name.py":
import sys
from re import sub
from __future__ import division
def toStr(num,digitsAfter=2):
"""Num to string with zero stripping"""
frmt = '%.' + str(digitsAfter) + 'f'
num = (frmt%num)
num = num.strip('0')
if num[0] =='.':
num = '0'+num
if num[-1] == '.':
num = num.strip('.')
return num
def tenpower(num,maximum=1e3,minimum=1e-2,base=1):
"""converts num to (num1,num2) where num1*10**num2=num
converts when not minimum<num<maximum.
converts until base<num1<2*base"""
pwr = 0
while abs(num) > maximum or (abs(num)>2*base and pwr>0):
pwr +=1
num = num / 10
while abs(num) < minimum or (abs(num)<base and pwr<0):
pwr -=1
num = num * 10
return num,pwr
def latexize(num,power=False,delim=','):
if power:
return ('%s \\cdot 10^{%d}' %(num,power)).replace('.',delim)
else:
return str(num).replace('.',delim)
if __name__ == "__main__":
#try:
argc = len(sys.argv)
var = 'Ooopsy-doopsy!'
digitsAfter = 2
typ = 10
if argc >1:
var = sub('[{}\. ]','',sys.argv[1])
comment = '\\comments{%s}'%sys.argv[1]
var = globals()[var]
else:
raise ValueError
if argc >2:
try:
digitsAfter = int(sys.argv[2])
except:
typ = sys.argv[2]
if argc >3:
typ = sys.argv[2]
digitsAfter = int(sys.argv[3])
mini=1/10**digitsAfter
if typ in ('int','i'):
print comment,int(var)
elif typ in ['float','f','nomath']:
print comment+latexize(toStr(var,digitsAfter))
else:
strings = tenpower(var,minimum=mini)
print comment+latexize(toStr(strings[0],digitsAfter),strings[1])
#except Exception:
# pass
P.S. Обрабатывать такой файл LaTeX нужно с опцией "-shell-escape"