Slepování jazyků pomocí Pythonu
Díky své univerzálnosti a rozšiřitelnosti dokáže Python spolupracovat s mnoha rozdílnými jazyky. Obvykle to je z pohledu programátora poměrně jednoduché. Musíme ovšem vědět, že ne vždy je použité řešení optimalizované pro rychlost. Mohou také existovat jistá omezení, týkající se např. kompatibility datových typů.
Velký přehled možností, jak integrovat Python s jinými jazyky, najdeme na wiki.python.org. My se podíváme na některé z jazyků a možností.
Nízkoúrovňové jazyky¶
Nízkoúrovňové jazyky už jsme použili pro optimalizaci, takže dobře víme, že jejich volání je poměrně snadné. Shrňme si, jaké jsou nejrozšířenější možnosti.
C/C++¶
C konvence (konkrétně cdecl) pro volání funkcí je asi nejrozšířenějším standardem. Pokud takové rozhraní umíme použít, případně vytvořit, máme k dispozici velké množství knihoven.
- Pro volání funkcí z dynamických knihoven můžeme použít
ctypes
. - [Cython](http://cython.org/] dovoluje volat C/C++.
-
scipy.weave
, Instant nebo Bitey umožňuje kompilovat C/C++ kód vložený přímo do Python kódu. - F2PY umožňuje příomčaře vytvořit Python rozhraní pro C funkci.
- Boost.Python zjednodušuje vytváření Python rozhraní pro C++.
- SWIG je tradiční nástroj pro integraci C/C++ do jiných jazyků, včetně Pythonu.
Fortran¶
-
F2PY umožňuje příomčaře vytvořit Python rozhraní pro Fortran funkci. Pro IPython existuje díky tomu kouzlo
%%fortran
. F2PY má sofistikovanou podporu pro NumPy pole. - Forthon dovoluje podobně jako F2PY kombinovat Fortran a Python, navíc podporuje struktury (derived types). Podobně jako F2PY, NumPy pole jsou předávána jen referencí (pokud jsou uložena ve Fortran uspořádání).
Vysokoúrovňové jazyky¶
Java¶
- Pokud používáme čistý Python bez rozšíření v C/Fortranu apod. (což je případ např. NumPy, Scipy aj.), je nejjednodušší použít Jython, což je interpret Pythonu běžící v Java virtuálním stroji. V Jythonu můžeme používat Java knihovny a naopak, Jython má rozhraní pro Javu.
- Py4J nebo JPYPE dovolují volat Javu z (C)Pythonu. Pyjnius je podobný projekt zaměřený na Android.
- Jepp umožňuje opak, tj. volání (C)Pythonu z Javy. Zdá se, že tento projekt je ovšem nedostatečně udržovaný a kompatibilní: http://gillius.org/blog/2012/01/java-and-python-with-jepp-or-not.html. Zde je třeba sledovat vývoj.
(Primárně) vědecké jazyky¶
Jazykům, které jsou primárně určeny pro vědu, numeriku, zpracování dat apod., se budeme věnovat trochu podrobněji. To, že pro Python existují nástroje pro integraci těchto jazyků, je velice důležité pro případný přechod na Python. Pokud totiž máme programy v nějakém z těchto jazyků, nemusíme je hned přepisovat do Pythonu, přesto je v Pythonu můžeme poměrně pohodlně používat. To může být pro mnoho lidí rozhodujícím faktorem pro (ne)použití nového nástroje, v našem případě Pythonu.
R¶
R je velice populárním nástrojem pro (statistické) zpracování dat. Zde je nutno poznamenat, že v Python světě slouží k podobným účelům R-kem inspirovaný projekt Pandas a také (poměrně mladý) ggplot, což je náhražka za oblíbený ggplot2 pro R. Asi hlavním nástrojem pro volání R z Pythonu je Rpy. Pojďme se podívat na jednoduchou ukázku.
import rpy2.robjects as robjects
pi_r = robjects.r['pi']
print(type(pi_r))
print(pi_r)
print(pi_r[0])
piplus2 = robjects.r('pi') + 2
print(piplus2)
print(piplus2.r_repr())
pi0plus2 = robjects.r('pi')[0] + 2
print(pi0plus2)
V následujícím příkladě definujeme v R funkci f, kterou následně i zavoláme.
robjects.r('''
f <- function(r, verbose=FALSE) {
if (verbose) {
cat("I am calling f().\n")
}
2 * pi * r
}
f(3)
''')
Funkci f můžeme také používat přímo v Pythonu. Nejprve ji uložíme do proměnné r_f
r_f = robjects.r['f']
print(r_f.r_repr())
A nyní už můžeme r_f
přímo volat:
print(r_f(3))
Data z R můžeme převádět do NumPy polí.
from rpy2.robjects.packages import importr
import numpy as np
datasets = importr('datasets')
ostatus = datasets.__rdata__.fetch('occupationalStatus')['occupationalStatus']
ostatus_np = np.array(ostatus)
ostatus_npnc = np.asarray(ostatus)
print(ostatus)
print(ostatus_np)
Rozdíl mezi ostatus_np
a ostatus_npnc
je v tom, že ostatus_npnc
je pouze pohled (view) na data R. Poznáme to např. podle příznaku owndata
.
print(ostatus_np.flags.owndata)
print(ostatus_npnc.flags.owndata)
IPython nám navíc pro zjednodušení poskytuje rozšíření rmagic
. Ukázka např. zde.
Matlab / Octave¶
Pro integraci s Matlabem existuje Python-MATLAB(R) Bridge. Nemá tak propracované možnosti jako rpy2, nicméně použít ho můžeme.
import pymatbridge
import os
import numpy as np
mlab = pymatbridge.Matlab()
mlab.start()
res = mlab.run_func('%s/matlab/www/demo_func.m'%os.path.dirname(pymatbridge.__file__), {'a': 10})
res['result']
Takto vypadá výsledek run_code
.
mlab.run_code('a=[1,3,7]')
get_variable
dokáže přenést proměnnou z Matlabu do Pythonu.
a = mlab.get_variable('a')
a
Výsledkem je (bohužel) string (unicode). Pomocí numpy.matrix
ho můžeme převést na numpy matici (musíme ovšem převést unicode na str).
np.matrix(str(a))
Matlab ukončíme, aby zbytečně neběžel na pozadí.
mlab.stop()
Takto zpřístupníme %%matlab
magic.
ip = get_ipython()
pymatbridge.load_ipython_extension(ip)
V Matlabu můžeme pak dělat cokoli, včetně grafů.
%%matlab
a = linspace(0.01,6*pi,100);
plot(sin(a))
grid on
hold on
plot(cos(a),'r')
Pomocí -i
a -o
můžeme posílat / získávat proměnné. Pozor, zdá se, že toto nefunguje spolehlivě pokud voláme %%matlab
vícekrát se stejnými proměnnými.
a = np.array([1,2,3])
%%matlab -i a -o x
x = 2 * a;
Proměnné z Matlabu přicházejí jako obejkty PyTables.
type(x)
print(np.array(x))
import oct2py
import numpy as np
Získáme instanci Octave.
oc = oct2py.Oct2Py()
Tento objekt obsahuje přímo základní funkce.
print(oc.abs(-1))
Funguje i Pythonovská nápověda.
help(oc.abs)
oct2py umí pracovat s NumPy poli pro vstup i výstup.
oc.svd(np.array([[1,2], [1,3]]))
Některé funkce v Octave (stejně jako v Matlabu), např. svd
, vrací jiný výstup podle počtu výstupních proměnných. I toto je v oct2py podporováno.
U, S, V = oc.svd([[1,2], [1,3]])
print(U)
print(S)
print(V)
IDL¶
Pokud se konečně chcete zbavit obludy jménem IDL) (Interactive Data Language) a nemáte čas všechny vaše programy hned přepisovat do Pythonu, pomůže vám pIDLy, případně ve spojení s ipython-idlmagic.
import pidly
Použijeme GDL, což je open source náhražka IDL (podobně jako Octave pro Matlab).
idl = pidly.IDL('/usr/bin/gdl', idl_prompt='GDL> ')
idl('x = total([1, 1], /int)')
Proměnné z IDL získáme takto
idl.x
nebo takto (tato varianta by měla být rychlejší)
print idl.ev('x')
Sezení ukončíme pomocí close
.
idl.close()
Pro notebook můžeme použít %idl
po instalaci rozšíření.
%install_ext https://raw.github.com/ebellm/ipython-idlmagic/master/idlmagic.py
%load_ext idlmagic
%idl
automaticky detekuje, zda použít IDL či GDL.
%idl print, findgen(5)
Mathematica¶
Pro integraci Mathematica existuje pythonica a také IPython rozšíření. Pro opačný proces, tj. použití Pythonu v Mathematice, lze použít pythonika.
Sage -> Maple, Maxima, Matlab, Octave, ...¶
Sage dokáže volat mnoho externích nástrojů, viz dokumentace.
Komentáře
Comments powered by Disqus