Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for named tuples #175

Open
rofinn opened this issue Jul 29, 2015 · 9 comments
Open

Support for named tuples #175

rofinn opened this issue Jul 29, 2015 · 9 comments

Comments

@rofinn
Copy link
Member

rofinn commented Jul 29, 2015

Currently the behaviour is to just convert named tuples in python to julia tuples, which obviously doesn't work if you want to pass that tuple to another python function that is expecting a named tuple.

@stevengj
Copy link
Member

If you want to leave it as a Python object, you can do so by using pycall. i.e. pycall(function_returning_named_tuple, PyObect, args....)

@stevengj
Copy link
Member

Julia doesn't have named tuples, so the alternatives here are

  • Current behavior: Default to converting to a Julia tuple, require an explicit PyObject if you want to keep it as a Python named tuple.
  • Default to returning a PyObject for named tuples, require an explicit convert if you want a Julia tuple. (However, since PyObject is iterable, you can maybe still use it like a tuple in some ways in Julia, even without calling convert.)
  • Convert to some other Julia type, e.g. a Vector{Pair{Symbol,Any}}.

@rofinn
Copy link
Member Author

rofinn commented Jul 30, 2015

So I'm kind of in favour of the third option where the julia type is a wrapper around the Vector{Pair{Symbol, Any}} called something like PyNamedTuple. For now I'll just try using pycall though.

@rofinn
Copy link
Member Author

rofinn commented Jul 30, 2015

So it turns out that if you use namedtuple = pycall(PyObject(my_python_func), PyObject, args...) the resulting PyObject still doesn't seem to store the names/keys, so passing that PyObject to another python function that expects a namedtuple will still result in an AttributeError on the keys/names and python still seems to think that the PyObject is just a tuple and not a namedtuple.

Ex)

julia> task = pycall(PyObject(arbiter.create_task), PyObject, length, "foo")
PyObject (<PyCall.jlwrap length>, 'foo', frozenset(), 0, datetime.timedelta(0), True, datetime.datetime(2015, 7, 30, 17, 16, 33, 654000))

julia> s[:add_task](task)
ERROR: PyError (:PyObject_Call) <class 'AttributeError'>
AttributeError("'tuple' object has no attribute 'name'",)
  File "/Users/rory/repos/Arbiter/.tox/py34/lib/python3.4/site-packages/arbiter/scheduler.py", line 102, in add_task
    if not Graph.valid_name(task.name):

 in pyerr_check at /Users/rory/.julia/v0.4/PyCall/src/PyCall.jl:58
 in pycall at /Users/rory/.julia/v0.4/PyCall/src/PyCall.jl:91
 in fn at /Users/rory/.julia/v0.4/PyCall/src/conversions.jl:188

@stevengj
Copy link
Member

Rory, you need to get the PyObject of my_python_func to start with. If you get the Julia wrapper, function, then convert it back to a PyObject, it won't work because the Julia wrapper function performs the conversion for you. (This will go away once I pull the trigger on #101.)

For example, if you want the method foo in module M, to get the raw PyObject of foo you can do pyimport("M")["foo"].

@rofinn
Copy link
Member Author

rofinn commented Jul 31, 2015

Awesome, thanks! Sorry, I didn't put two and two together with your pycall and pyimport documentation. Also, I really look forward to the #101 change 👍

@stevengj
Copy link
Member

stevengj commented Nov 2, 2017

Now that Julia 0.7 has a NamedTuple type (#22194), it should be possible to fully support bidirectional conversion to/from Python named tuples.

@tkf
Copy link
Member

tkf commented Mar 15, 2019

I'm actually opposed to automatically converting Python's named tuple to Julia's. This is because Python's named tuples use nominal type whereas Julia's named tuples use structural type. It means that it is impossible to get the right named tuple from Python-Julia-Python round trip.

@baggepinnen
Copy link

baggepinnen commented Mar 8, 2021

I think it would be much better to default to returning a PyObject rather than converting the python namedtuple into a julia tuple. The python code

nt = fun1()
fun2(nt)

can not be replaced with the julia version

nt = py.fun1()
py.fun2(nt)

since the named tuple nt has been butchered by the automatic conversion.

The automatic conversion appears to be destroying my object even if I do

some_and_nt = pycall(ts.load_params, PyObject, args...)

where some_and_nt is a tuple of something and a named tuple in python. Here, I declare that I want to get a PyObject back, but when I acces some_and_nt[2] to pass the namedtuple into another function, it has been converted to a julia tuple and the call fails.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants