Repository navigation
Docs: note requirement to normalise unicode identifiers passed to globals() and locals() #86846
Description
Activity
outofculture commented
on Dec 19, 2020 outofculturemannequinMannequinAuthorMore actionsThis behavior is best described by the code below:
>>> meow = 1 >>> 'meow' in globals() True >>> µmeow = 1e-6 >>> 'µmeow' in globals() False >>> globals()['woof'] = 1 >>> woof 1 >>> globals()['µwoof'] = 1e-6 >>> µwoof Traceback (most recent call last): File "<stdin>", line 1, in <module> NameError: name 'μwoof' is not defined >>> import sys >>> sys.getdefaultencoding() 'utf-8' >>> [(k, bytes(k, 'utf-8')) for k in globals()] ..., ('μmeow', b'\xce\xbcmeow'), ('µwoof', b'\xc2\xb5woof')] >>> 'µ'.encode('utf-8') b'\xc2\xb5'Testing was done on linux and windows, variously using 3.6.12, 3.7.6, 3.8.6 and 3.9.0+.
- added3.7 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.9 (EOL)end of lifeend of lifetype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Dec 19, 2020 outofculture commented
on Dec 19, 2020 outofculturemannequinMannequinAuthorMore actionsOh, I just gave a cursory using
locals(), and the same misbehavior is present.A workaround, for anyone needing to assign or access unicode globals, is to use
exec, e.g.exec("µmeow = 1e-6", globals()).I'm pretty sure this is not a bug, but is working as designed.
The interpreter normalises unicode identifiers, but key lookup in the dict does not.
Sorry, I don't have time right now to give a more detailed answer, but there are two distinct mu characters:
μ U+03BC µ U+00B5and my prediction is that the identifier is normalised to the first, the actual Greek mu, but you are looking up the second, the micro sign.
(I'll be able to give a longer response in a couple of hours, if still needed.)
outofculture commented
on Dec 19, 2020 outofculturemannequinMannequinAuthorMore actionsAh! So then the proper code for me would be e.g.:
>>> globals()[unicodedata.normalize("NFKC", "µmeow")] 1e-06Yes, it's clear when I read https://www.python.org/dev/peps/pep-3131/ that the normalization is going to happen. Is it also worth adding a note in the documentation for
globals()andlocals()? That's the first place I looked to try to find out what was wrong.I think documenting this with globals() and locals() is a good idea. That's the place this is most likely to trip someone up.
3 remaining items
- addeddocsDocumentation in the Doc dirDocumentation in the Doc dir3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixesand removed3.9 (EOL)end of lifeend of life3.8 (EOL)end of lifeend of life3.7 (EOL)end of lifeend of life
on Aug 1, 2024 Updated issue title and labels to reflect the previous discussion.
- marked Unicode is normalised after keywords are checked for #77886 as a duplicate of this issue
on Sep 26, 2025 - removed3.13only security fixesonly security fixes3.14bugs and security fixesbugs and security fixes
on Sep 26, 2025 - linked a pull request that will close this issuegh-135676: Simplify docs on lexing names #140464
on Oct 22, 2025 Documented as a note in https://docs.python.org/3.15/reference/lexical_analysis.html#non-ascii-characters-in-names
I think that's the proper place, as that where Python does the normalization.
globals()itself is perfectly fine with non-normalized keys:>>> fix = False >>> globals()['fix'] False >>> globals()['fix'] = True >>> globals()['fix'] TrueLet's reopen if someone disagrees.
Metadata
Metadata
Assignees
Labels
Projects
- StatusShow more project fieldsTodo
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields: