PyCall Workaround for Automatic Conversion, Looking for Alternative

So here is a solved problem, but it feels like I have solved it incorrectly, and I would love to know if there is a better way.

I want to create a PyObject using the Body constructor from this library. Here is a basic MWE that works.

const astropy_units = pyimport("astropy.units") 
const poliastro_body = pyimport("poliastro.bodies").Body

const AU = 1.49597870691e8 # km
const MU = 1.32712440018e11 # km^3/s^2

Orbit_Builder_Sun = py"[exec('import poliastro.bodies as pbd'), pbd.Body(parent=None,k = $MU * ($ ** 3 / $astropy_units.s ** 2), name='Sun')][-1]"o

println(Orbit_Builder_Sun) # prints -> PyObject Sun (None)

The above works because if you run something as a single line of Python, py"..."o returns the results as an object. The structure of that line is the way it is to be able to import and run Body on the same line.

So that’s really un-intuitive. Here is what I thought would work but does not:

Orbit_Builder_Sun = poliastro_body(
     k = MU * ( ^ 3 / astropy_units.s ^ 2),
println(Orbit_Builder_Sun) # prints -> (nothing, fill(1.32712440018e11), "Sun", nothing, fill(0.0), fill(0.0), fill(0.0), fill(0.0), fill(0.0), fill(0.0), fill(1.9884098709677421e21))

The version of the code that I thought would work does not return a PyObject, and so I can no longer pass it to functions that need to use it.

This can’t be the intended workflow, could someone provide some insight into how I could do this in a “better” way

I believe you can replace poliastro_body(...) with pycall(poliastro_body, PyObject, ...) to force it to return a PyObject.


(Or use PythonCall which does no such automatic conversion.)

1 Like