Problem with spawning a python3 process on Windows

Hello,

I’m trying to get my app working on Windows and I can’t figure out what the issue is. Everything works flawlessly on Linux(Xubuntu) but when I’m trying to run my app on Windows I’m constantly getting these errors. It looks like Phoenix can’t spawn python3 instances, but I don’t know why. I am 100% sure that python3 is installed and matches the path that Phoenix is trying to use.

Hasn’t anyone run into a similar issues on Windows?
Any ideas?

$ python -V
Python 3.10.2

[error] GenServer #PID<0.631.0> terminating
** (stop) :enoent
    erlang.erl:2217: :erlang.open_port({:spawn, 'c:\\Users\\Jiri\\AppData\\Local\\Microsoft\\WindowsApps\\python3.exe -V'}, [{:line, 80}, :stderr_to_stdout, :hide])
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/erlport_options.erl:227: :erlport_options.get_version/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python_options.erl:177: :python_options.check_python_version/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python_options.erl:161: :python_options.find_python/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python_options.erl:146: :python_options.get_python/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python_options.erl:88: :python_options.parse/2
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python.erl:168: :python.start/3
    (pluto 0.1.0) lib/pluto/image/pil_worker.ex:112: Pluto.Image.PilWorker.handle_info/2
    (stdlib 3.12) gen_server.erl:637: :gen_server.try_dispatch/4
    (stdlib 3.12) gen_server.erl:711: :gen_server.handle_msg/6
    (stdlib 3.12) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:create_port, "c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/_build/dev/lib/pluto/priv/python"}
State: %{arg: "c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/_build/dev/lib/pluto/priv/python", max_size: nil, port: nil}

I have 0 experience with Windows Elixir and Python.

You cmd line example calls python but the error calls python3.exe. Are you sure the file name is correct and exists at that path?

My bad, sorry! Either way, both python3 and python output the same result

$ python3 -V
Python 3.10.2
$ python -V
Python 3.10.2

python3.exe does exist inside the folder and even outputs the same result

$ c:\\Users\\Jiri\\AppData\\Local\\Microsoft\\WindowsApps\\python3.exe -V
Python 3.10.2

I’m honestly confused why it’s not working.
I can’t even run python calling

:erlang.open_port({:spawn, 'python -V'}, [{:line, 80}, :stderr_to_stdout, :hide])
 or
:erlang.open_port({:spawn, 'python3 -V'}, [{:line, 80}, :stderr_to_stdout, :hide]) 

There may be a $PATH issue.

Have you tried?

path = "C:\\Users\\Jiri\\AppData\\Local\\Microsoft\\WindowsApps\\python3.exe"
Port.open({:spawn_executable, path}, [:binary, args: ["-V"]])

This solution does not work, either.

C:\Users\Jiri>iex
Interactive Elixir (1.13.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> path = "C:\\Users\\Jiri\\AppData\\Local\\Microsoft\\WindowsApps\\python3.exe"
"C:\\Users\\Jiri\\AppData\\Local\\Microsoft\\WindowsApps\\python3.exe"
iex(2)> Port.open({:spawn_executable, path}, [:binary, args: ["-V"]])
** (ErlangError) Erlang error: :enoent
    erlang.erl:2217: :erlang.open_port({:spawn_executable, "C:\\Users\\Jiri\\AppData\\Local\\Microsoft\\WindowsApps\\python3.exe"}, [:binary, {:args, ["-V"]}])
iex(2)>

Curious. And what do you get from System.find_executable("python") as per `'Port - spawn_executable docs?

The output is following

iex(2)> System.find_executable("python")
"c:/Users/Jiri/AppData/Local/Microsoft/WindowsApps/python.exe"

Ah ok I see, try to use that output.

path = System.find_executable("python")
Port.open({:spawn_executable, path}, [:binary, args: ["-V"]])

I think it was my fault for misunderstanding the way erlang output the path name vs. elixir.

Environment variable ERLPORT_PYTHON can be set to python interpreter path. ErlPort tries to pick up from this env variable by default.

1 Like

Sadly, no luck. It gives the same error.

iex(1)> path = System.find_executable("python")
"c:/Users/Jiri/AppData/Local/Microsoft/WindowsApps/python.exe"
iex(2)> Port.open({:spawn_executable, path}, [:binary, args: ["-V"]])
** (ErlangError) Erlang error: :enoent
    erlang.erl:2217: :erlang.open_port({:spawn_executable, "c:/Users/Jiri/AppData/Local/Microsoft/WindowsApps/python.exe"}, [:binary, {:args, ["-V"]}])

It may be a dumb question, but how can I change the path?
However, even the current path points to a valid path.

You can set it in command prompt - but it wont persist between sessions

Ahh, understood, thanks! However, even when ERLPORT_PYTHON is set, the path is not picked up and shows the old output.

You made sure environment variable was set by printing them using command set in command prompt? If it is not reflecting you can open new command prompt or powershell.

This is weird - ERLPORT_PYTHON picks up everytime I set and restart iex.

What I did was

c:\Users\Jiri\Desktop\Phoenix\Pluto\phx>set ERLPORT_PYTHON=C:\
c:\Users\Jiri\Desktop\Phoenix\Pluto\phx>echo %ERLPORT_PYTHON%
C:\
c:\Users\Jiri\Desktop\Phoenix\Pluto\phx>mix phx.server
[warning] Phoenix is unable to create symlinks. Phoenix' code reloader will run considerably faster if symlinks are allowed. On Windows, the lack of symlinks may even cause empty assets to be served. Luckily, you can address this issue by starting your Windows terminal at least once with "Run as Administrator" and then running your Phoenix application.
[info] Running PlutoWeb.Endpoint with cowboy 2.9.0 at 127.0.0.1:4000 (http)
[info] Access PlutoWeb.Endpoint at http://localhost:4000
[debug] QUERY OK db=16.0ms idle=16.0ms
SELECT * FROM get_all_settings() []
[debug] Maid started to clean images
[debug] %Postgrex.Query{cache: :reference, columns: nil, name: "", param_formats: nil, param_oids: nil, param_types: nil, ref: nil, result_formats: nil, result_oids: nil, result_types: nil, statement: "SELECT get_all_photos()", types: nil} uses unknown oid(s) 29239forcing us to reload type information from the database. This is expected behaviour whenever you migrate your database.
[debug] QUERY OK db=0.0ms queue=15.0ms idle=63.0ms
SELECT get_all_photos() []
[warning] Could not get files from upload directory. reason: :enoent. path: c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/_build/dev/lib/pluto/priv/upload
[info] Maid finished cleaning task (thumbnails enqueued)
[error] GenServer #PID<0.566.0> terminating
** (stop) :enoent
    erlang.erl:2217: :erlang.open_port({:spawn, 'c:\\Users\\Jiri\\AppData\\Local\\Microsoft\\WindowsApps\\python3.exe -V'}, [{:line, 80}, :stderr_to_stdout, :hide])
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/erlport_options.erl:227: :erlport_options.get_version/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python_options.erl:177: :python_options.check_python_version/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python_options.erl:161: :python_options.find_python/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python_options.erl:146: :python_options.get_python/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python_options.erl:88: :python_options.parse/2
    (erlport 0.10.1) c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/deps/erlport/src/python.erl:168: :python.start/3
    (pluto 0.1.0) lib/pluto/image/pil_worker.ex:112: Pluto.Image.PilWorker.handle_info/2
    (stdlib 3.12) gen_server.erl:637: :gen_server.try_dispatch/4
    (stdlib 3.12) gen_server.erl:711: :gen_server.handle_msg/6
    (stdlib 3.12) proc_lib.erl:249: :proc_lib.init_p_do_apply/3
Last message: {:create_port, "c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/_build/dev/lib/pluto/priv/python"}
State: %{arg: "c:/Users/Jiri/Desktop/Phoenix/Pluto/phx/_build/dev/lib/pluto/priv/python", max_size: nil, port: nil}

I have also tried placing the environment variable in system settings

If I set environment variable and it is invalid path - it will be giving different error

iex(1)> :python.start()
{:error, {:invalid_env_var, {'ERLPORT_PYTHON', '/sdf'}, :not_found}}

Your stacktrace is different. Are you passing options to :python.start() ?

In my web app, this piece of code is used

:python.start_link(
        python: String.to_charlist("python3"),
        python_path: String.to_charlist(python_path)
      )

I now created a new project to test things out, and despite the fact that no options are provided, I still get an error.

$ iex -S mix
Interactive Elixir (1.13.3) - press Ctrl+C to exit (type h() ENTER for help)
iex(1)> :python.start()
** (ErlangError) Erlang error: :enoent
    erlang.erl:2217: :erlang.open_port({:spawn, 'c:\\Users\\Jiri\\AppData\\Local\\Microsoft\\WindowsApps\\python.exe -V'}, [{:line, 80}, :stderr_to_stdout, :hide])
    (erlport 0.10.1) c:/Users/Jiri/Desktop/gg/deps/erlport/src/erlport_options.erl:227: :erlport_options.get_version/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/gg/deps/erlport/src/python_options.erl:177: :python_options.check_python_version/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/gg/deps/erlport/src/python_options.erl:161: :python_options.find_python/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/gg/deps/erlport/src/python_options.erl:132: :python_options.get_python/1
    (erlport 0.10.1) c:/Users/Jiri/Desktop/gg/deps/erlport/src/python_options.erl:88: :python_options.parse/2
    (erlport 0.10.1) c:/Users/Jiri/Desktop/gg/deps/erlport/src/python.erl:168: :python.start/3

Can you try this once in iex - does it work ?

:python.start([{:python, 'c:/Users/Jiri/AppData/Local/Microsoft/WindowsApps/python.exe'}])

I’ll give it a go on Monday, sadly, I’m out of the office and I have no issues with my laptop, which runs on Linux.
I am pretty sure it will not work, there’s something wrong with Python installed via WindowsApps.
I’ve been told to install Python through an external source, which is supposed to fix the issue.

Thanks for your help, I’ll give you an update on Monday!

App execution alias thing i guess