# ExternalEvaluate for Python fails with Import::nopythonevals

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?

• 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.) – Michael E2 Sep 15 '17 at 11:24
• 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). – b.gatessucks Sep 15 '17 at 12:16
• @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). – Szabolcs Sep 15 '17 at 12:44
• Yes this is a bug and is reported to appropriate developer to look at. Thanks – dsingh Sep 15 '17 at 16:55
• Hi, @b.gatessucks , this doesn't work. pasteboard.co/GMUO8KS.png – matheorem Oct 1 '17 at 12:58

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 *)

ExternalEvaluateImportExportPrivate$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. 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 *) ExternalEvaluatePrivate$LanguageHeuristics["Python", "ExecutablePathFunction"]
`