admin管理员组

文章数量:1125929

I am developing a library supporting Python 3.10+ and, in a lot of ocasions, I find myself importing libraries just because I need a class for type hints.

This is very common, for example:

import pandas as pd

# Prev code where `pd` is never used

def myfunc() -> pd.DataFrame:
    # Definition of my func where `pd` is never used

# Rest of code where `pd` is never used

I want to implement the way to use type hints to reduce the most the overhead in runtime added by importing libraries and/or classes.

I am considering the next options:

  1. Adding from __future__ import annotations everywhere and not adding the imports.
  2. Creating a types module in my library that imports the specific class that I will be using for type hints, such as from pandas import DataFrame as pandasDF and then using this module where required.
  3. Importing the specific class from pandas import DataFrame where I will be using the type hint.
  4. Just accepting that I will need to import the module or the class. This is, the pattern that was shown at the beginning.

The question is: what is the most optimized way (in terms of extra runtime added) to set the classes that will be used for type hints?

I am currently importing the module containing the class where required.

I am developing a library supporting Python 3.10+ and, in a lot of ocasions, I find myself importing libraries just because I need a class for type hints.

This is very common, for example:

import pandas as pd

# Prev code where `pd` is never used

def myfunc() -> pd.DataFrame:
    # Definition of my func where `pd` is never used

# Rest of code where `pd` is never used

I want to implement the way to use type hints to reduce the most the overhead in runtime added by importing libraries and/or classes.

I am considering the next options:

  1. Adding from __future__ import annotations everywhere and not adding the imports.
  2. Creating a types module in my library that imports the specific class that I will be using for type hints, such as from pandas import DataFrame as pandasDF and then using this module where required.
  3. Importing the specific class from pandas import DataFrame where I will be using the type hint.
  4. Just accepting that I will need to import the module or the class. This is, the pattern that was shown at the beginning.

The question is: what is the most optimized way (in terms of extra runtime added) to set the classes that will be used for type hints?

I am currently importing the module containing the class where required.

Share Improve this question edited Jan 9 at 3:23 InSync 10.3k4 gold badges15 silver badges51 bronze badges asked Jan 9 at 2:41 César Arroyo CárdenasCésar Arroyo Cárdenas 516 bronze badges 9
  • The most optimized way is, obviously, not to use type hints at all (and use stub files instead). This has a very unfortunate consequence of you yourself not having autocomplete and such during development. Does that answer your question? – InSync Commented Jan 9 at 3:25
  • 1 If you go for option 2, keep in mind that types already exists and you probably don't want to shadow it. – Aemyl Commented Jan 9 at 7:07
  • @InSync, it does answer the question in a more general way. I was thinking more of "what is the most optimized way without making the mentioned sacrifice". – César Arroyo Cárdenas Commented Jan 9 at 7:22
  • 3 I think you may benefit from understanding that once you've imported a library somewhere in your code, then the next time you do import pandas is won't reload the library, that is, imports are cached. Note, from module import x doesn't avoid importing the whole module, it just changes what is added to the current namespace. it is equivalent to import module; x = module.x; del module – juanpa.arrivillaga Commented Jan 9 at 7:33
  • 1 @juanpa.arrivillaga I mean that I am not explicitely using it in my module. That is, in the code in my module, pd never shows up anywhere else. Think wrapping QueryJob.to_dataframe(). You are right in that, if I'm using this method, there is some internal place in biquery.job where pandas is imported. – César Arroyo Cárdenas Commented Jan 9 at 7:49
 |  Show 4 more comments

2 Answers 2

Reset to default 2

The short answer is the use a guarded type-checking block:

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    import pandas  # <-- no longer imported at runtime

x: "pandas.DataFrame"

You can safe the typing import by doing

TYPE_CHECKING = False
if TYPE_CHECKING:  # <-- type-checkers still treat it as True
    import pandas

Depending on your python version (3.7-3.11) from __future__ import annotations can help to prevent runtime errors and making quoted type hints unnecessary.


There are some tools that help you to detect and "fix" such import automatically. Primarily this is flake8-type-checking which is also implemented by ruff. Depending on your IDE there should be extensions that allow you to run such checks in realtime and provide you with the necessary fixes.

Command line options are normally available too, e.g. for ruff:

ruff check . --select TC001,TC002,TC003,TC004

The TC001-003 rules check if annotations can be moved into an type-checking block and TC004 if something needs to be moved outside.

There's actually a built-in feature for this: typing.TYPE_CHECKING

This is simply a boolean that is True at type checking time, and False at runtime. If your imports are only required at type checking time you can say:

import typing

if typing.TYPE_CHECKING:
    import pandas as pd

def myfunc() -> pd.DataFrame:
    pass

Hope this helps!

本文标签: pythonQuickest method to use type hints when the needed type comes from another libraryStack Overflow