pyo3
pyo3 copied to clipboard
Bikeshedding names: `Py` and `PyObject`
Having written this fairly innocent comment in #863:
I've been wondering what happens if we renamed
PyObjectto justObject- I don't think thePyis particularly interesting and typingPy<Object>is heck of a lot less annoying thanPy<PyObject>. This would be a good moment to do such a rename if we're breaking everything anyway.
It seems like a few people had ideas and opinions about what we could do on this point, mostly focussing on renaming Py.
Rather than let that discussion sidetrack from discussion in #863, I thought it best to open this issue.
The current names Py, and PyObject are fine, though I am always open to improving things if there's a strong community opinion for one thing over another. To be clear though, a rename of such core pieces like this would cause a lot of churn to all pyo3 users - so if we do this, let's wait until we're totally confident on the names we like, and then do the rename once only.
Some proposals of alternative names for Py:
PyRc
Some proposals of alternative names for PyObject:
An interesting option is what rlua does; types are not Lua prefixed in the API, but they are in
rlua::preludeto avoid confusion.
I've used PyO3 on some projects for my previous employer, I'm doing some work on rust-numpy rn, and I've been planning to use PyO3 in an existing project (https://github.com/PTNobel/AutoDiff).
I'll say that I don't know what Py does at all, I'm just assuming there's some magic behind it. PyRc makes me think that this is a object that is being reference counted by the python interpreter (is this even correct?).
I personally don't like the type name of Object as I do think the prefix is good and useful to remember that the type originates in Python and I'm not just storing a Rust type named Object in the Python arena [is that even possible? I'm not positive.].
PyRc makes me think I can't pass it safely between threads as its rc rather than arc. There's a lot of 'Py' in pyo3 - it's not particularly distinguishing given how much its used...
Another name that I wonder about for Py is PyHandle - inspired by the HPy proposal.
This seems to be more of an open discussion rather then a concrete thing we want to get done. I believe that since it has been open for more than an year with no real traction we should leave the naming as is for now. Personally, I prefer the current naming and I don't see any good alternative. @davidhewitt Can we close this for now? :)
Do we want to deprecate+remove the alias pub type PyObject = Py<PyAny>;? I don't like it very much, and removing it should probably be done before 1.0
I would also like to not have PyObject / PyAny any more.
I was personally planning to leave the current pair of names as-is, and in #1308 introduce replacements (probably just PyObject, as I think that's more common terminology than PyAny, however discussion on that PR can decide). I'll try to comment my current thinking on that PR soon.
Was just going to write a long thing about this in a new issue, but since this exists, I'll do it here.
Py is a super-confusing name
The current naming of Py is a really bad UX thing that I suspect confuses many new users, and certainly as an intermittent PyO3 user I keep hitting this.
In PyO3 code, you will have:
- A
pyvariable, an instance ofPython<'_>. Py<T>, which looks just like thepyabove.
This leads to multiple problems:
- Every time I come back to PyO3 I have to remember that
pyisn't aPy, it's aPython. - Even worse, the meaning of
Pyis the opposite ofpy!pygives you the lifetime that ties things to the GIL being held,Pymeans the object is not tied to GIL being held. Py<PyList>is not at all meaningful unless you go read a bunch of docs.
This is super-confusing, and gets me every single time. I would suggest getting this done before 1.0 is pretty critical (I started working on Twisted in 2001, and 20 years later it still suffers from bad naming we made back then that we never fixed. I do recommend taking the time to improve naming.)
Some alternatives
RustOwned<T>: explain what it does, at the cost of being verbose.O3<T>: short, gives you a hint that this is tied to the Rust side of things, starting withOmeans it's easier to remember it's tied ownership.O3Rc<T>: slightly less short, bit more understandable if you're familiar with Rust.
PyObject is also confusing
pyo3::types::PyList is a Rust-y wrapper for pyo3::ffi::PyList, which is the Rust name for CPython's PyList. Same for tuple etc..
In contrast, pyo3::PyObject is not the Rust-y wrapper for pyo3::ffi::PyObject.
Some alternatives
Maybe just... get rid of PyObject? Especially if a succinct replacement for Py is chosen.
Also for consistency it seems like PyAny ought to be called PyObject? But that's a double deprecation cycle.
Just going to bump this, with an example. I think renaming Py is the most useful and helpful change, and worth doing as soon as possible.
Current API:
// Create a Python list that can be stored without holding the GIL;
// notice that Py and py have opposite meanings!
let list: Py<PyList> = PyList::empty(py).into();
// Create another Py<PyList> that points to the same underlying Python list:
let list2 = list.clone();
// Get a reference to the underlying list that we can more easily interact with:
let direct_reference_to_list: &PyList = list.as_ref(py);
With O3Rc as alternative:
// Create a Python list that can be stored without holding the GIL:
let list: O3Rc<PyList> = PyList::empty(py).into();
// Create another O3Rc<PyList> that points to the same underlying Python list;
// notice that because it's called O3Rc it's much clearer that this doesn't actually
// copy the underlying data, at least to Rust programmers:
let list2 = list.clone();
// Get a reference to the underlying list that we can more easily interact with:
let direct_reference_to_list: &PyList = list.as_ref(py)
A third usage of "py" (in addition to Py<_> and py: Python<_>) is the namespace tag &'py. This is convention, but it's convention that means you need to parse a third meaning. An obvious replacement is &'gil, except that the GIL might be going away...
Sorry for not replying faster. I still am generally in support of making some renaming here, although I think it will require a solid new proposal as well as already a good migration plan to make this feasible for users.
I agree with your categorization of the three usages of the "py" name as conflicting at the moment. My current "ideal" solution is related to #1056 and to give Py<'py, PyAny> as an owning and gil-bound type. The existing Py<T> could be moved to some other name like PyDetached<T> or PyArc<T> etc. There is a lot of discussion in #3205 about why this is not great with current Rust (requires the nightly arbitrary_self_types feature).
With Py<'py, PyAny> then I think the Py type and 'py lifetime gain compatible meanings. I think 'py lifetime also fits well with Python<'py> as the indicator we're connected to the Python interpreter, so the usage of "py" is then harmonious.
For PyObject vs PyAny, personally I think the ship might have sailed and PyAny is too prevalent now. It's also compatible with Python's typing.Any concept, and shorter to type, so I think PyAny will stay. We can definitely consider what to do about the PyObject type alias, though I don't think it's as confusing as the "py" issue discussed above.
I think having two kinds of PyObject (the alias and the ffi thing) is pretty confusing, so I'd like to get rid of the alias.
Given Bound<'_, T> is now a thing, and that Py<T> is the opposite of Bound<'_, T>, maybe Py<T> could be renamed to Detached<T> or Unbound<T>.
I am certainly tempted to do that. The one thing holding me back is that "contexts" as a future Rust feature might remove the need to have Py and Bound as separate types. I plan to blog about this sometime soon. Is Py a suitable name if we were to merge the two? I'm not sure, need to think more.
For removing PyObject alias, I am generally still 👍 for this. I think the heaviest usage of the alias is in the IntoPy and ToPyObject traits. Figuring out the future of those traits will help us remove the alias IMO.