I know there is some support for running Mathematica from Python, but is there any way to do the reverse. For example, to import some Python classes and use them in Mathematica?

  • related: mathematica.stackexchange.com/q/1894/5 (I don't know enough to tell if it's a dupe or not) – rm -rf Dec 3 '12 at 21:59
  • @rm-rf: Different: that relies on .NET. – orome Dec 3 '12 at 22:01
  • 2
    Google Pythonika – Mark McClure Dec 3 '12 at 22:19
  • 3
    @Jens He says he wants "to import some Python classes and use them in Mathematica". That's exactly what Pythonika does. I've used it to run sage from Mathematica. One of the dumbest things I've ever done, but I did it: facstaff.unca.edu/mcmcclur/Mathematica/Sage – Mark McClure Dec 3 '12 at 22:40
  • 2
    @MarkMcClure: Pythonica seems not to be a viable solution. I can't get it to load (0S X 10.8.2, Python 2.7.2, Mathematica 9.0). Are there any alternatives? – orome Dec 12 '12 at 1:52

Building off of @M.R.'s idea, it is possible to set up an interactive python shell using StartProcess as opposed to RunProcess, allowing for much more flexible connectivity between Python and Wolfram without as much overhead. In it's simplest form, one can open a connection, interact with it, and close it using the following example:

path = "e:\\Programs\\python27\\python"; (*insert OS-appropriate path \
to python*)
p = StartProcess[{path, "-i"}]; (*the'-i' argument is important*)
cmd = "print 'hello'"; (*or any valid python expression*)
Pause[1]; (* important!!! *)
WriteLine[p, cmd];
out = ReadString[p, EndOfBuffer]
KillProcess@p;

Pausing after the StartProcess call is important in order to avoid the cmd being sent to the python interpreter before it has finished loading. A much shorter pause can be used on faster computers.

I've put together a short package to streamline python interactivity. The version I've posted below also reads the python shell text (which is delivered on stderr) and prints that to the Message window if the FrontEnd is active or simply Prints it if the command line is being used. It works nicely with simple commands pcmd@"print 'hello'" and I've had success with some sophisticated operations such as web scraping with Splinter and BeautifulSoup. It coughs when trying to use something like Tkinter, but it just doesn't work as opposed to throwing some form of error, making it a bit difficult to debug.

BeginPackage["wlPython`"];

$pythonprocess = Null;
    $pythonpath = "e:\\Programs\\python27\\python";
$pythonpause = 0.250; (* Pause in seconds to receive error information *)
startPython::usage = "Starts the python process";
endPython::usage = "Ends the python process";
pcmd::usage = "issue a python command";


(* Check for FrontEnd and set as appropriate, can be overridden *)
$pyfrontend = $FrontEnd=!=Null;

Begin["`Private`"];

Clear[startPython]
startPython[path_:$pythonpath]:=Module[{err},
    	$pythonprocess = StartProcess[{path,"-i"}];
    wlPython`pyerrcheck[];
    $pythonprocess 
]

Clear[endPython]
endPython[process_:Unevaluated@$pythonprocess]:=Module[{},
    KillProcess@Evaluate@process;
    NotebookWrite[MessagesNotebook[],
    Cell[RawBoxes@ToBoxes["Python process ended",TraditionalForm],"Output"]];
]

Clear[pcmd]
pcmd[cmd_String,process_:Unevaluated@$pythonprocess]:=Module[{status,err,out,p},
    p = Evaluate[process];
    status = ProcessStatus[p];
    If[status=="Running",
    WriteLine[p,cmd];
    wlPython`pyerrcheck[];
    out = ReadString[p,EndOfBuffer]
    ];
    out
]

Clear[pyerrcheck]
pyerrcheck[]:=Module[{err},
    Pause@$pythonpause;
    	err = ReadString[ProcessConnection[$pythonprocess,"StandardError"],EndOfBuffer];
    If[$pyfrontend,
        NotebookWrite[MessagesNotebook[],
        Cell[RawBoxes@ToBoxes[err,TraditionalForm],"Output"]];,
        Print[err];
    ]

]

End[];

EndPackage[];

Here is a more robust solution using Process:

Clear[runPython];
runPython::badCommand  ="Python code failed to run with message `StandardError`";
$pyimports="from random import randint
";
runPython[str_String, imports_:$pyimports] := Module[
    {pyscrpt = ToString[$pyimports<>str, CharacterEncoding->"ASCII"], file=CreateTemporary[], res},
    Export[file,pyscrpt,"Text"];
    res = RunProcess[{"/anaconda/bin/python",file}];
    DeleteFile[file];
    If[res["ExitCode"]!=0, 
        Return @ Failure["badCommand",<|"MessageTemplate" :> runPython::badCommand,"MessageParameters"-> <|"Message" -> res["StandardError"]|>|>],
        Return @ ImportString @ res["StandardOutput"]
    ]
]

enter image description here

I had to use anaconda's python executable - Mathematica was crashing the system's python runtime.

  • " Here is a more robust solution using Process:" More robust than what? – Brian Moths Nov 30 '16 at 19:33
  • 1
    Than the original answer from @raxa... – M.R. Dec 2 '16 at 19:11
  • did you mean to write (...) ToString[imports<>str (...) in the second line of the definition of the function? The way it is now the second argument of runPython is useless – glS Jan 14 '17 at 21:06
  • This (excellent and previously accepted) answer is outdated as of 11.2. – orome Mar 14 at 17:52

If all you want is to invoke Python scripts and use the output they generate in Mathematica, then simply

pythonOutput = Import["!python fullpathtoscript/your_scipt.py --some_opt arg arg ...", "String"];

is sufficient.

  • Commands like this don't work at all for me in Mathematica 10.0.1. – Mike Nov 21 '14 at 3:44
  • It works for me in Mathematica 10.0.2.0. – ThomasH Apr 6 '15 at 18:55
  • @ThomasH: Can you give me a specific example of something that works that I can try. It doesn't even work for me anymore (10.0.2.0). – orome Apr 6 '15 at 20:24
  • For a MWE, I made a file in my home directory called test.py containing "print('hello world')", then in Mathematica (also pointed at my home directory by default), 'Import["!python test.py","String"]' produces the string "hello world". I have a simple but slightly more complicated example I can point you to on github if you'd like. – ThomasH Apr 9 '15 at 17:14
up vote 7 down vote accepted

Since 11.2 Mathematica has supported ExternalEvaluate and since 11.3 this functionality has been conveniently available simply by beginning an input cell with > which produces an external code cell:

enter image description here

The output of these cells is a Wolfram Language expression that you can then compute with.

  • 1
    Please clarify with an example, say, for Python, including when Python is not the default OS system installation but another, e.g., anaconda's. – murray Mar 14 at 19:06
  • 1
    @murray: Was that the OP's question? – orome Mar 14 at 19:54

Here is an approach that works on Mac OS X or unix-like systems without the need to explicitly create any temp directory:

code = "print \\\"hello, starting\\\"
for i in [1,2,3]:
\t print i*i
 "

(* ==> 
"print \\\"hello, starting\\\" 
for i in [1,2,3]:
     print i*i
"
*)


RunProcess[$SystemShell, "StandardOutput", 
 "printf \"" <> code <> "\" | python
  exit
  "]

(* ==>
"hello, starting
1
4
9
"
*)

First, I define the string containing the Python code. I included a test message to illustrate how you have to escape the quotation marks using \\\" inside the string, because it's going to be passed into a printf command on the shell command line. THat printf is subsequently piped into python. Note that I didn't have to specify the path because it's found from the SystemShell environment.

The interaction with Mathematica takes place via RunProcess, and the standard output of the Python script is directly captured into Mathematica. Again, it's not necessary to bother with any temporary files in this approach.

  • Can you contrast this with the Import approach? Is it just that it avoids using an existing script? FWIW, I'd never write the Python code in the Mathematica environment: the code editing tools are just too poor. – orome Apr 5 '15 at 14:14
  • Also, can you show how it would work with an existing script? – orome Apr 5 '15 at 14:21
  • @raxacoricofallapatorius Yes, my main point is to have the script and everything it needs completely inside Mathematica. If you already have an existing script outside Mathematica, then it's not a real two-way interaction, I'd say. But what to do with an existing script specifically would depend on the application. I can't think of anything general to say about that, except that it would be possible, e.g., to pass arguments to it using my approach. An important advantage of my approach is, however, that it makes the entire process portable: you can email the notebook without attachments. – Jens Apr 5 '15 at 16:13
  • Yes; also, it looks like the approach I had no longer works. – orome Apr 5 '15 at 18:19
  • 2
    Oh well, that's just a formatting error when I manually tried to put the python string into a form that looks right in the code cell above. One extra space crept in, and that kills python. I fixed it. If it still doesn't work, it could be dependent on the OS and version of Mathematica. This RunProcess command doesn't work in earlier versions... by the way, another way of interacting with python is through the clipboard on Mac. But I don't know what your actual goal is, so I'll skip that for now. – Jens Apr 5 '15 at 21:19

There's a "Python link" called Pythonika. I have used it briefly and it works.

What it does:

  • translates basic data types, including arbitrary size integers, to/from Python
  • makes it possible to implement functions in Python and call them from Mathematica

It does not provide any means to work with classes directly. Also, the implementation is rather hackish using unsafe practices (e.g. symbols are not localized to a context, and this has bitten me). To implement a link properly it would take lot more work.

I made a few basic fixes (e.g. using contexts), but I haven't used the thing in a long time. Contact me if you want the fixes.

  • Does nt compile and does nt work. – User12309 Aug 12 '14 at 20:01
  • 1
    Correct, it is deprecated and seems no longer maintained... – M.R. Jan 26 '15 at 2:36
  • Hi, @Szabolcs, is there librarylink way use of python in Mathematica? – matheorem Sep 5 '16 at 14:19
  • @matheorem There's no simple way. LibraryLink or MathLink won't solve the problem of transferring and converting data structures between Python and Mathematica. Someone would have to think about how that conversion should work and implement it on top of LibraryLink or MathLink. (Actually the right choice is MathLink here in my opinion.) That is a job that would take several weeks of full time work, even for a simple version. I don't know who has time for that. – Szabolcs Sep 5 '16 at 14:22
  • @Szabolcs If there is no librarylink for python, then with Pythonika you mentioned, is it possible to write python function that exploit power of numy and scipy, and calling it in Mathematica? How efficient is that? – matheorem Sep 5 '16 at 14:27

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Not the answer you're looking for? Browse other questions tagged or ask your own question.