Process Create Path of Executable

Hello,

I use process_create/3 to communicate with Python scripts.

I call the predicate this way:

process_create(
   path(python),
   [SymPyScript],
   [stdout(pipe(OSTerminalOutputStream))]
).

This works fine for Windows, but in Linux I get an error that Python cannot find an imported module included in the script SymPyScript.

What is exactly path(python)? How is it set? Does it copy the variable PYTHONHOME in Ubuntu for example? I am asking this because I have a few Python versions in my system, and one of them is included in Anaconda and contains the imports I need.

Many thanks.

This says that you want to use the command python and you want Prolog to find it based on SWI-Prolog knowledge of file paths, e.g.

?- file_search_path(path,Path).

If you look at the top of the documentation for library(process): Create processes and redirect I/O it notes

In addition to the predicates, this module defines a file search path (see user:file_search_path/2 and absolute_file_name/3) named path that locates files on the system’s search path for executables. E.g. the following finds the executable for ls :

?- absolute_file_name(path(ls), Path, [access(execute)]).

I suspect that

?- absolute_file_name(path(python),Path).

will work on Windows and fail on Linux.

HTH


EDIT

As Jan W. points out below, my intent in writing this was to suggest that on your machine you might try to use

?- absolute_file_name(path(python),Path).

as a test to disseminate where the problem lies. The way the accompanying text reads, it implies that this will always fail on Linux which I know is clearly not true.

1 Like

PYTHONHOME, PYTHONPATH, etc. are Python-specific, and SWI-Prolog knows nothing about them … absolute_file_name/3 is used to resolve a file specification (such as path(python)) to a file name.

I suspect that something is going on with the “current directory” being different in Windows and Ubuntu. To figure this out, you could try this Python program:

import os, sys
print(sys.argv)
print(os.path.dirname(sys.argv[0])) # directory part of the executable
print(sys.path)

This should show you the result of applying PYTHONHOME, PYTHONPATH, etc. If sys.path doesn’t contain your module’s path, you can try something like the following (gets the executable name from sys.argv, puts its directory first in sys.path):

sys.path.insert(0, os.path.dirname(sys.argv[0]))

On my system, it seems that the Python executable puts the executable’s directoyr first; if your module is in some other place, you might need to do something like
sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), 'my_module_dir').

Resolving Python modules (and packages, which are not quite the same thing) is a bit of a black art - e.g., be sure you have __init__.py files (even if empty). If you’re looking in stackoverflow, Thomas Wouters is authoritative (user:17624). E.g.,

1 Like

Note that Python seems to be found and started. create_process/3 uses absolute_file_name/3 with the option file_type(executable) as well, which notably make it try and add the Windows executable extensions.

The OP’s problem is most likely with the environment variables (which are simply passed if noting is specified) or the working directory (which is also unchanged unless specified).

1 Like

This is for me more of a blackhole than black art :slight_smile:
I tried playing along your suggestions but my technical (dirty) knowledge approaches zero.

I found this juicy piece of evidence though: this is the error I get when my Prolog program fails.

ImportError: No module named sympy
ERROR: -g prove(‘/home/amine/problems/’,‘problem.txt’): Process “/usr/bin/python”: exit status: 1

So I guess this means that Prolog is looking for the python inside /usr/bin

and this is my path:

$ echo $PATH
/home/amine/tools/ext/anaconda3/bin:/home/amine/tools/ext/anaconda3/condabin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin

The python that should be invoked is the python in anaconda:

$ which python
/home/amine/tools/ext/anaconda3/bin/python

but the one invoked is:

/usr/bin/python

Any ideas?

Bit weird. Prolog is indeed started with this environment? You can check how Prolog interprets $PATH using this, enumerating all solutions.

?- file_search_path(path, X).

This should also succeed:

?- access_file('/home/amine/tools/ext/anaconda3/bin/python', execute).

You can also set this to see what is being tried when searching for a file:

?- set_prolog_flag(verbose_file_search, true).

And there is this to verify Prolog agrees on $PATH

?- getenv('PATH', X).

I’ve found that anaconda does weird things to the environment – for example, it made tkdiff use weird fonts. Maybe try conda deactivate and see what happens?

(Also, python might resolve do a different version on your two systems; I like to specify the version, e.g. python3.7).

If you’re using Python 2, I recommend switching to Python 3. It allows more options with import, such as from ..someDir import foo. I was able to resolve my module-loading problems by using the from . import style.

It was Anaconda messing my stuff, I installed SymPy not using Anaconda and it worked. Thanks everyone for your help.

With all the Anaconda and Python things, I have developed serious Ophidiophobia.

When I transitioned to doing some serious coding with Python I installed Anaconda and then just started regretting it more and more. Granted Anaconda is great if you buy-in into the entire philosophy but it wrecked havoc with my normal means of work.

The next time I re-image my machine, Anaconda is not getting installed on the base machine. If I do need it it will probably be put/accessed as a Python development container for use with VSCode remote development.

I feel your pain!