Why are python imports renamed with leading underscores
Asked Answered
C

2

7

I noticed it at work with functools.partial and also in python source code itself. E.g. below from collections.py

from operator import itemgetter as _itemgetter, eq as _eq
from keyword import iskeyword as _iskeyword
import sys as _sys
import heapq as _heapq

What is the rationale for doing so? If this was C++ I understand it could cause namespace conflicts however in python wouldn't these names be local to the module in which they are imported? Unless someone does import *, but that's discouraged so I'm not sure that's the reason.

Colquitt answered 6/11, 2017 at 13:56 Comment(3)
Thats is a convention, it means that the developer wants those names to be private. Is telling you that you should not use them from this module, but from the original library.Swimmingly
But thats the thing, who would want to use sys itemgetter from this module? I see in other places sys is just imported as is without a _ prefix E.g. svn.python.org/projects/python/trunk/Lib/BaseHTTPServer.pyColquitt
It is a matter of coding style, I think. But I agree is not common practice, at least in import statements.Swimmingly
S
5

This indicates that the function, variable or class is private. Not only is it a human convention (so you should know not to use it), but python also enforces that it will not be imported in certain conditions.

From PEP8:

_single_leading_underscore: weak "internal use" indicator. E.g. from M import * does not import objects whose name starts with an underscore.

PS: Using import * is not good practice, but that's another discussion.

Sallie answered 6/11, 2017 at 14:27 Comment(2)
Thanks. Perhaps it sticks out because in none of the python books do I see import sys renamed as _sys. Sincethe sys module comes with the python installation I'm struggling to understand who would want to import sys from this module (which imports it as _sys)Colquitt
@Colquitt Imagine you are running import * from mymodule. You also also have a variable called sym, but you mistyped it sys. Now, because mymodule exposed sys, this will silently succeed and use sys instead of throwing a used before defined error. A contrived example, but it shows why you wouldn't want to expose more than you need from your module. Of course, this is also solved by not using import * and only importing what you need.Malca
S
0

As it was already mentioned, the leading underscore indicates a private/internal variable, which is just a convention in Python; you are still able to import and use it.

What I wanted to add is that I usually recommend against renaming import in projects unless you are building a reusable package or it is a well-established import rename, like import pandas as pd.

Motivation is the following:

  • Most modern IDEs will add imports automatically and if you work on the project together with somebody who will rename imports you will end up with different import styles
  • It makes debugging and reading code harder. When somebody sees something like logging.getLogger(__name__) he expects logging to be standard library logging. But once you start using import renames, there can be import my_custom_logging as logging at the top. And when you or anybody else is reading the code he needs to look at the imports, which is very inconvenient.
  • Depending on what you import and rename, the IDE's refactoring functionality will probably behave unexpectedly.
  • This will force you to think about naming twice. As we already know naming is one of the hardest things in software development, thinking about naming from the usage perspective will results in better naming for modules, classes, functions, variables.
Semipro answered 18/12, 2023 at 8:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.