Skip to content

object has different identities during and after import #2687

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

Closed
dhalbert opened this issue Mar 7, 2020 · 7 comments
Closed

object has different identities during and after import #2687

dhalbert opened this issue Mar 7, 2020 · 7 comments

Comments

@dhalbert
Copy link
Collaborator

dhalbert commented Mar 7, 2020

nested.py:

l = [[]]
l0 = l[0]

print("l[0]", id(l[0]))
print(l0, id(l0))
Adafruit CircuitPython 3.1.2 on 2019-01-07; Adafruit Metro M0 Express with samd21g18
>>> from nested import *
l[0] 536876704
[] 536876704
>>> id(l[0])
536876704
>>> id(l0)
536896144   # should not be different from id(l[0])
>>> 

In CircuitPython 2.x, MicroPython, and CPython the id() values are the same in the REPL. My guess is that this has to do with making an object long-lived during compilation, since this shows up in 3.x.

Thanks @TG-Techie for spotting this. This is reduced from a real program, in which he was fetching and assigning some empty lists nested inside some tuples during an import, and then found out they were not the same lists when referenced by subscript outside.

Tagging @tannewt.

@dhalbert dhalbert added this to the 5.x.x - Bug Fixes milestone Mar 8, 2020
@tannewt
Copy link
Member

tannewt commented Mar 9, 2020

I think the correct thing would be to have the later id of l[0] be 536896144. I don't mind that the ids themselves change after import but we should create two separate objects.

I do agree that this is a long lived issue because we assume that only one reference of module variable exist. (We recurse from the module dict down and don't look elsewhere for references.)

I don't think this is urgent and would argue for it to be "Long Term" because there is a simple and easy workaround: Just assign l0 = l[0] after the import rather than in the module.

@TG-Techie
Copy link

TG-Techie commented Mar 11, 2020

@tannewt I agree it should be ling term. I think very few people will find this bug and the temporary fix is quite easy.

It could be that I am miss-interpreting "the correct thing would be to have the later id of l[0] be 536896144":
I think that the object shouldn't be made into a separate copy after import. I think that would be perfectly acceptable for immutable objects like ints, strs, tuples, etc but mutable objects should not be duplicated. I think when the list is edited in the repl it should change in the module.

to me, this seems intuitively correct because any import in python is really just syntactic sugar for the import function for getattring objects from inside it (with the .). thus if the same module is imported into two other python files they (I believe) should both be getting references to the same list object b/c the lists is within the same module object.
like how from time import sleep is equivalent to sleep = __import__('time').sleep

@TG-Techie
Copy link

meta importers and other CPython extensibilities aside

@tannewt
Copy link
Member

tannewt commented Mar 11, 2020

@tannewt I agree it should be ling term. I think very few people will find this bug and the temporary fix is quite easy.

It could be that I am miss-interpreting "the correct thing would be to have the later id of l[0] be 536896144":
I think that the object shouldn't be made into a separate copy after import. I think that would be perfectly acceptable for immutable objects like ints, strs, tuples, etc but mutable objects should not be duplicated. I think when the list is edited in the repl it should change in the module.

It's not meant to be a copy (that is the bug). It is meant to be a move. The id will change but it will change consistently between the two objects. If you add a function that will print the id from within the module's scope then the new id should be there as well. The object is moved at the end of the import and the existing prints are before that.

@TG-Techie
Copy link

TG-Techie commented Mar 11, 2020

Ah, I did misinterpret.

@jepler
Copy link

jepler commented Jun 22, 2023

Restating this without use of id:

Put the following in nested.py:

# content of nested.py
l = [[]]
l0 = l[0]

and the following in code.py:

# runtime
import nested
nested.l0.append("test")
print(nested.l)

With python3, it prints [['test']], while with circuitpython it prints [[]], because in circuitpython nested.l0 and nested.l[0] are not the same object due to the implementation of "long lived" being unable to move objects.

@dhalbert
Copy link
Collaborator Author

Fixed by #8281, which removed long-lived allocations, and so removed objects moving around after creation.

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