Define Python function in Julia file with PythonCall?

Context: I have a Pluto notebook for teaching where I need to create a Python function. I want to use PythonCall for better portability, but I miss the py"..." syntax of PyCall which allows you to directly define Python functions inside Julia code. Is there a workaround to importing the function from a file? I looked at @py but it doesn’t seem to work for my case.

2 Likes

Do you require the function to be defined in Python, or could you use something like pyfunc as described in Reference - PythonCall - Create classes ?

Ideally I’d want the function to be defined in Python to demonstrate the Julia speed up. Dumping on Python is my favorite pastime

3 Likes
julia> using PythonCall

julia> fib(x) = pyexec("""
       def fib(n):
            a, b = 0, 1
            while a < n:
                print(a, end=' ')
                a, b = b, a+b
            print()
       fib(y)
       """, Main, (y=x,))
fib (generic function with 1 method)

julia> fib(10)
0 1 1 2 3 5 8

https://cjdoris.github.io/PythonCall.jl/stable/pythoncall-reference/#PythonCall.pyexec

6 Likes

Thanks a bunch!

1 Like

For future reference, we don’t need to redefine the Python function every time we call the Julia one, we can also access local variables within it:

julia> fib(n) = pyexec(
           @NamedTuple{a::Int},
           """
           a, b = 0, 1
           for k in range(n):
               a, b = b, a + b
           """,
           Main,
           (n=n,)
       )
fib (generic function with 1 method)

julia> fib(10)
(a = 55,)

Whenever you use pyexec you’re invoking the Python parser, which makes for an unfair comparison. It’s better to use it to create a Python function then call that:

@pyexec """
def fib(n):
   a, b = 0, 1
   while a < n:
       print(a, end=' ')
       a, b = b, a+b
   print()
""" => fib

fib(10)

This example uses @pyexec’s handy => notation for getting variables into and out of Python.

9 Likes

Thanks, that’s exactly what I was looking for

Thanks for the great extension to the PythonCall doc! What I can’t get to work yet is an import within the literal code, or some way to get an import (e.g. numpy) to work in or around your fibonacci. There must be a way?
Thanks for any tips!

1 Like

@cjdoris sorry for the necroposting but I find myself interested in this question again. Is there a way to achieve that?

1 Like