Erlport is undefined or private

I’m still learning Elixir,and am making a basic elixir program to call a function from a python program. I am attempting to use erlport to do so. However, in the code below Erlport is undefined. I don’t see what could be causing it.

defmodule RarFile do
  @moduledoc """
  Documentation for `RarFile`.
  """

  @doc """
  Hello world.

  ## Examples

      iex> RarFile.hello()
      :world

  """
  

  def extractor(filepath) do
    {:ok, pid} = :erlport.open_port({:spawn, "python"}, [:binary, :stream, packet: 4])


  end

end

Here is the mix.exs file that I’m using.

defmodule RarFile.MixProject do
  use Mix.Project

  def project do
    [
      app: :rar_file,
      version: "0.1.0",
      elixir: "~> 1.14",
      start_permanent: Mix.env() == :prod,
      deps: deps()
    ]
  end

  # Run "mix help compile.app" to learn about applications.
  def application do
    [
      extra_applications: [:logger]
    ]
  end

  # Run "mix help deps" to learn about dependencies.
  defp deps do
    [

      {:erlport, "~> 0.10"}
      # {:dep_from_hexpm, "~> 0.3.0"},
      # {:dep_from_git, git: "https://github.com/elixir-lang/my_dep.git", tag: "0.1.0"}
    ]
  end
end

hi @Tormenator1 please always include a copy and paste of the exact error when asking about an error.

In glancing at the docs found here ErlPort - Python documentation the function you are trying to use is never mentioned, are you sure you’re calling a function that exists?

You are confusing erlport eith Elixir Port, they are not the same…

You should do something like this example…

:python.start([{:python_path, to_charlist(path)}, {:python, 'python3'}])

# and

:python.call(pid, :your_python_script, :your_python_function, [params1, params2])

FWIW, open_port is a built-in Erlang function.

Erlport provides wrappers to open ports to Python and Ruby executables, you should use one of those if that’s what you’re looking to do.

I have multiple python environments on the development machine. How would I select a specific one?

Also, when enetering the first line of code you provided I get this error.

(SyntaxError) keyword argument must be followed by space after: python:
|
18 | {ok, PythonInstance1} = python:start()
| ^

Stacktrace:
│ (elixir 1.14.4) lib/kernel/parallel_compiler.ex:340: anonymous fn/5 in Kernel.ParallelCompiler.spawn_workers/7

No idea how is your setup…

But starting my release with Systemd, I can pass Python environment variables.

That is not Elixir code, but Erlang, it should be…

{:ok, pi1} = :python.start()

… in Elixir. And beware with the strings, they are not really the same between Elixir and Erlang

I am using this exact line when i get the error above.

:python.start([{:python_path, to_charlist(path)}, {:python, 'python3'}])

Elixir thinks that this is a syntax error.

I get a similar error when I try this line from the language docs

{ok, P} = python:start()

(SyntaxError) keyword argument must be followed by space after: python:
|
18 | {ok, P} = python:start()
| ^

Stacktrace:
│ (elixir 1.14.4) lib/kernel/parallel_compiler.ex:340: anonymous fn/5 in Kernel.ParallelCompiler.spawn_workers/7

Why exactly would this be happening?

Erlport is an Erlang package, so the doc is written in Erlang…

I advise You to read this page, if You want to translate from Erlang to Elixir

No, I did not provide code written in Erlang :slight_smile:

So the python file is called handler.py and the function I am calling is called hey. It accepts 1 string parameter.

How would I call that function in this code. I’m unclear about what is meant to be passed into the call function in terms of the module parameter?

{:ok, pi1} = :python.start()
:python.call(pi1,,hey,"hi") #left module blank,unsure what is passed there

It should look like this…

Thank you. Wrote a line in that format calling another function called rar_extraction. Here’s the total code I have so far

defmodule RarFile do

  archive_path = 'extractor/Kickassv301.cbr'
  destination_folder = 'extractor/extracted'


  def extractor(filepath) do
    {:ok, pi1} = :python.start()
    :python.call(pid1, :handler, :rar_extraction, [archive_path, destination_folder])

  end

end

However,I get a error from the ninth line that says

(CompileError) undefined function archive_path/0 (expected RarFile to define such a function or for it to be
imported, but none are available)

What could be causing this?

Move the variables inside the function.

Or if you want them to be accessible for the entire module, make them module attributes.

2 Likes

No need to use charlist here, You can use binaries…

But it is only half of the problem, because the Python part is tricky to setup. You’ll need to do some conversion of data in the Python script. Something like this…

    if isinstance(path, bytes):
        path = path.decode("utf-8")
        if not os.path.exists(path):
            return ("error", "path does not exists.")
    else:
        return ("error", "cannot decode path.")

Hi, I’ve just released Doumi.Port - A helper library that facilitates the usage of Python in Elixir.

This library will make it much easier to use Python in Elixir.
Thanks!