22
$\begingroup$

I tried using ExternalEvaluate on OS X with Anaconda Python, and every ExternalEvaluate call failed with the Import::nopythonevals message. This happened even though an external evaluator was successfully registered, and pyzmq was installed in Anaconda Python.

What is the problem?

enter image description here

$\endgroup$
7
  • 3
    $\begingroup$ I have a Python copy in /usr/local/bin (MacOS), soft-linked to the Anaconda binary, which is found by the automatic process. No need to register it, either. (Just a note for those who cannot reproduce the problem.) $\endgroup$
    – Michael E2
    Sep 15, 2017 at 11:24
  • $\begingroup$ I use the "Executable" specification, as in StartExternalSession[<|"System" -> "Python", "Executable" -> "C:\\dev\\bin\\Anaconda\\envs\\1.9.1.post520\\python.exe", "ReturnType" -> "String"|>] and everything works (Win 64). $\endgroup$ Sep 15, 2017 at 12:16
  • 1
    $\begingroup$ @b.gatessucks The situation is this: ExternalEvaluate (not StartExternalSession) will fail if the builtin heuristics of ExternalEvaluate (which are OS-specific) are unable to find a python executable that has zmq set up. If this happens, it does not matter that you have specified an executable manually, or registered one. Importing PythonExpressions will fail regardless. This is why I consider it a bug: when I specify the Python executable manually, the system should use it (not try to find it elsewhere on its own and then fail). $\endgroup$
    – Szabolcs
    Sep 15, 2017 at 12:44
  • 2
    $\begingroup$ Yes this is a bug and is reported to appropriate developer to look at. Thanks $\endgroup$
    – dsingh
    Sep 15, 2017 at 16:55
  • $\begingroup$ Hi, @b.gatessucks , this doesn't work. pasteboard.co/GMUO8KS.png $\endgroup$
    – matheorem
    Oct 1, 2017 at 12:58

2 Answers 2

16
$\begingroup$

To get this out of the way:

I believe the Import::nopythonevals message will be issued by Import[..., "PythonExpression"] if there are no usable external evaluators set up. First make sure that you have set up Python correctly (including installing pyzmq), and registered an external evaluator.


As you can see in my question, I have already done this, yet ExternalEvaluate was not working.

To cut a long story short, I believe that this is due to a bug in M11.2.0 where Import[..., "PythonExpression"] attempts to find a Python installation on its own, and does not even look at what installations the user has already registered using RegisterExternalEvaluator.

In my case, it was trying to use the system Python on OS X. I suspect it failed because I did not have pyzmq installed for the system Python. I prefer not to modify it, as I use a private installation of Anaconda Python instead.

Here's a workaround to force Import[..., "PythonExpression"] to use the Python installation that I have already registered:

ExternalEvaluate (* triggers loading the ExternalEvaluate framework *)
(* ExternalEvaluate *)

ExternalEvaluate`ImportExport`Private`$ImporterPythonSession = StartExternalSession["Python" -> "String"] (* this evaluator will be used to handle "PythonExpression" *)
(* ExternalSessionObject["9a23363e-5403-442d-8fbd-39f9aff7dc48"] *)

py = StartExternalSession["Python"]
(* ExternalSessionObject["5022a77c-eedb-4d39-bbb3-c8b6a644ecdf"] *)

ExternalEvaluate[py, "1+1"] (* now everything works fine! *)
(* 2 *)

I hope this information will be useful to others who want to play with ExternalEvaluate, but do not wish to modify (or even use) their system Python on OS X.

enter image description here


As mentioned by @MichaelE2, an alternative solution is to symlink your preferred Python interpreter in a location that is already being searched by the ExternalEvaluate framework. Currently, on OS X and Linux /usr/local/bin/ is such a location. To see the full list of locations, evaluate

ExternalEvaluate (* load framework *)
ExternalEvaluate`Private`$LanguageHeuristics["Python", "ExecutablePathFunction"] 
$\endgroup$
2
$\begingroup$

Not sure if you already resolved your issue - I literally beat my head against the wall for 6 weeks straight fighting the same about 5 months ago. I finally resolved the issue - it's a syntax error in the externalevaluate.py script. Follow my simple solution and hope this helps everyone:

  1. Locate externalevaluate.py should be in:
C:\Program Files\Wolfram Research\<Wolfram Finance Platform>\3.0\SystemFiles\Links\WolframClientForPython\wolframclient\utils\

[note: Swap with whichever version of Mathematica you are using, or whichever is your sub-folder under \Program Files\Wolfram Research<your folder name>...]

  1. Open in whichever editor you use (e.g., Notepad++), and replace line 66 as follows:

    exec(compile(ast.Module(expressions, []), '', 'exec'), current) 
    

    this is the part you copy and replace what is in line 66 with this. Very minor change, and voile!

  2. You should restart 12.x and you will find ExternalEvaluate is no longer throwing that error, and opening up a Python shell "shift >" also works just as well. Of course, you will still need to use ExternalEvaluate, however, this is amazing integration!

Now, if Wolfram could post this online in their actual docs hopefully others do not lose as much sleep as I did. :)

Side note — Do not attempt to use Chocolatey to trick Mathematica into updating from 3.7.0 to 3.8.x - it will hang and freeze. What needs to be done is the ability to SystemInstall whichever version of Python we want to install as opposed to being bound to 3.7.0. Sure you can register various versions then restart, but that is not as tightly integrated as the 3.7.0 version SystemInstall does for us.

Let me know if this works for you, it did for me especially when invoking a shell "shift >" inside of a notebook, then trying to install modules...Little trick for you, just type the following for installing modules from within the shell:

import os
os.popen('pip install <module name>') # of course without the <>.

or,

import os
os.system('pip install <module name>')

Hope this helps Mathematica v12.x users get up and running with Python and use an external evaluate shell within a notebook (.nb file) quickly.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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