Skip to content

Conversation

@pjonsson
Copy link

@pjonsson pjonsson commented Oct 2, 2025

It takes a while to import
platform, so use sys.platform
to check for macOS/Linux, and
only import platform to detect
BSD dialects.

Tested inside a python:3.10-bookworm container with a test.py containing:

import typer.main

and then python3 test.py followed by:

python3 -X importtime test.py > timing.txt 2>&1

a couple of times. Times fluctuate a bit, but here's a reasonable before:

import time: self [us] | cumulative | imported package import time: 91 | 91 | _io import time: 17 | 17 | marshal import time: 178 | 178 | posix import time: 353 | 638 | _frozen_importlib_external import time: 59 | 59 | time import time: 94 | 152 | zipimport import time: 25 | 25 | _codecs import time: 266 | 291 | codecs import time: 232 | 232 | encodings.aliases import time: 345 | 867 | encodings import time: 154 | 154 | encodings.utf_8 import time: 50 | 50 | _signal import time: 20 | 20 | _abc import time: 125 | 144 | abc import time: 165 | 309 | io import time: 25 | 25 | _stat import time: 91 | 116 | stat import time: 511 | 511 | _collections_abc import time: 79 | 79 | genericpath import time: 112 | 190 | posixpath import time: 439 | 1255 | os import time: 120 | 120 | _sitebuiltins import time: 279 | 279 | _distutils_hack import time: 41 | 41 | sitecustomize import time: 28 | 28 | usercustomize import time: 466 | 2186 | site import time: 165 | 165 | types import time: 346 | 510 | enum import time: 38 | 38 | _sre import time: 486 | 486 | sre_constants import time: 182 | 668 | sre_parse import time: 154 | 859 | sre_compile import time: 54 | 54 | itertools import time: 68 | 68 | keyword import time: 37 | 37 | _operator import time: 129 | 165 | operator import time: 83 | 83 | reprlib import time: 62 | 62 | _collections import time: 424 | 854 | collections import time: 28 | 28 | _functools import time: 279 | 1160 | functools import time: 35 | 35 | _locale import time: 128 | 128 | copyreg import time: 301 | 2991 | re import time: 86 | 3076 | fnmatch import time: 45 | 45 | errno import time: 197 | 197 | zlib import time: 171 | 171 | _compression import time: 131 | 131 | _bz2 import time: 170 | 470 | bz2 import time: 234 | 234 | _lzma import time: 174 | 407 | lzma import time: 347 | 4541 | shutil import time: 83 | 83 | __future__ import time: 85 | 85 | collections.abc import time: 478 | 478 | _ast import time: 447 | 447 | contextlib import time: 498 | 1422 | ast import time: 84 | 84 | _opcode import time: 134 | 217 | opcode import time: 311 | 528 | dis import time: 125 | 125 | warnings import time: 104 | 229 | importlib import time: 98 | 327 | importlib.machinery import time: 94 | 94 | token import time: 509 | 602 | tokenize import time: 78 | 679 | linecache import time: 778 | 3731 | inspect import time: 1042 | 1042 | typing import time: 578 | 578 | gettext import time: 130 | 130 | math import time: 144 | 144 | _datetime import time: 432 | 706 | datetime import time: 152 | 152 | _weakrefset import time: 236 | 388 | weakref import time: 250 | 637 | click._compat import time: 463 | 463 | threading import time: 80 | 543 | click.globals import time: 178 | 178 | click.utils import time: 216 | 936 | click.exceptions import time: 771 | 3049 | click.types import time: 149 | 149 | click._utils import time: 191 | 191 | click.parser import time: 110 | 301 | click.formatting import time: 136 | 136 | click.termui import time: 620 | 9686 | click.core import time: 154 | 154 | click.decorators import time: 173 | 10095 | click import time: 10 | 10105 | click.exceptions import time: 85 | 85 | typer.colors import time: 383 | 383 | signal import time: 111 | 111 | fcntl import time: 39 | 39 | msvcrt import time: 87 | 87 | _posixsubprocess import time: 85 | 85 | select import time: 321 | 321 | selectors import time: 336 | 1360 | subprocess import time: 1255 | 2615 | platform import time: 213 | 213 | traceback import time: 44 | 44 | _winapi import time: 33 | 33 | nt import time: 28 | 28 | nt import time: 27 | 27 | nt import time: 28 | 28 | nt import time: 238 | 395 | ntpath import time: 70 | 70 | urllib import time: 686 | 686 | ipaddress import time: 604 | 1359 | urllib.parse import time: 408 | 2161 | pathlib import time: 156 | 156 | _uuid import time: 254 | 409 | uuid import time: 122 | 122 | typer._types import time: 171 | 171 | typer._typing import time: 84 | 84 | importlib._abc import time: 166 | 250 | importlib.util import time: 176 | 176 | click.shell_completion import time: 85 | 85 | shellingham._core import time: 89 | 173 | shellingham import time: 217 | 390 | typer._completion_shared import time: 167 | 981 | typer._completion_classes import time: 599 | 599 | typer.models import time: 142 | 142 | typer.params import time: 36 | 36 | org import time: 7 | 43 | org.python import time: 7 | 49 | org.python.core import time: 96 | 145 | copy import time: 121 | 266 | typer.utils import time: 131 | 2117 | typer.completion import time: 959 | 959 | typer.core import time: 574 | 9337 | typer.main import time: 151 | 24217 | typer import time: 9 | 24225 | typer.main 

And here's a reasonable after:

import time: self [us] | cumulative | imported package import time: 100 | 100 | _io import time: 17 | 17 | marshal import time: 177 | 177 | posix import time: 333 | 625 | _frozen_importlib_external import time: 61 | 61 | time import time: 92 | 152 | zipimport import time: 27 | 27 | _codecs import time: 269 | 296 | codecs import time: 188 | 188 | encodings.aliases import time: 331 | 814 | encodings import time: 93 | 93 | encodings.utf_8 import time: 40 | 40 | _signal import time: 25 | 25 | _abc import time: 157 | 181 | abc import time: 165 | 346 | io import time: 30 | 30 | _stat import time: 104 | 134 | stat import time: 612 | 612 | _collections_abc import time: 87 | 87 | genericpath import time: 137 | 224 | posixpath import time: 457 | 1425 | os import time: 125 | 125 | _sitebuiltins import time: 270 | 270 | _distutils_hack import time: 40 | 40 | sitecustomize import time: 28 | 28 | usercustomize import time: 537 | 2422 | site import time: 171 | 171 | types import time: 335 | 506 | enum import time: 37 | 37 | _sre import time: 522 | 522 | sre_constants import time: 192 | 714 | sre_parse import time: 143 | 893 | sre_compile import time: 53 | 53 | itertools import time: 69 | 69 | keyword import time: 44 | 44 | _operator import time: 212 | 255 | operator import time: 164 | 164 | reprlib import time: 77 | 77 | _collections import time: 419 | 1035 | collections import time: 29 | 29 | _functools import time: 302 | 1366 | functools import time: 36 | 36 | _locale import time: 120 | 120 | copyreg import time: 299 | 3217 | re import time: 78 | 3294 | fnmatch import time: 40 | 40 | errno import time: 196 | 196 | zlib import time: 170 | 170 | _compression import time: 135 | 135 | _bz2 import time: 129 | 433 | bz2 import time: 160 | 160 | _lzma import time: 124 | 284 | lzma import time: 300 | 4546 | shutil import time: 78 | 78 | __future__ import time: 136 | 136 | collections.abc import time: 457 | 457 | _ast import time: 413 | 413 | contextlib import time: 487 | 1355 | ast import time: 111 | 111 | _opcode import time: 174 | 284 | opcode import time: 319 | 603 | dis import time: 136 | 136 | warnings import time: 135 | 271 | importlib import time: 101 | 371 | importlib.machinery import time: 80 | 80 | token import time: 481 | 560 | tokenize import time: 74 | 634 | linecache import time: 867 | 3828 | inspect import time: 1043 | 1043 | typing import time: 560 | 560 | gettext import time: 142 | 142 | math import time: 149 | 149 | _datetime import time: 456 | 746 | datetime import time: 150 | 150 | _weakrefset import time: 198 | 348 | weakref import time: 225 | 572 | click._compat import time: 327 | 327 | threading import time: 80 | 407 | click.globals import time: 181 | 181 | click.utils import time: 236 | 824 | click.exceptions import time: 786 | 2926 | click.types import time: 167 | 167 | click._utils import time: 179 | 179 | click.parser import time: 108 | 286 | click.formatting import time: 135 | 135 | click.termui import time: 601 | 9679 | click.core import time: 175 | 175 | click.decorators import time: 159 | 10089 | click import time: 8 | 10097 | click.exceptions import time: 86 | 86 | typer.colors import time: 433 | 433 | signal import time: 127 | 127 | fcntl import time: 41 | 41 | msvcrt import time: 78 | 78 | _posixsubprocess import time: 80 | 80 | select import time: 269 | 269 | selectors import time: 323 | 1349 | subprocess import time: 259 | 259 | traceback import time: 37 | 37 | _winapi import time: 32 | 32 | nt import time: 29 | 29 | nt import time: 28 | 28 | nt import time: 27 | 27 | nt import time: 123 | 274 | ntpath import time: 64 | 64 | urllib import time: 711 | 711 | ipaddress import time: 494 | 1269 | urllib.parse import time: 400 | 1942 | pathlib import time: 1121 | 1121 | platform import time: 165 | 165 | _uuid import time: 313 | 1599 | uuid import time: 123 | 123 | typer._types import time: 114 | 114 | typer._typing import time: 71 | 71 | importlib._abc import time: 115 | 186 | importlib.util import time: 166 | 166 | click.shell_completion import time: 82 | 82 | shellingham._core import time: 84 | 166 | shellingham import time: 208 | 374 | typer._completion_shared import time: 171 | 895 | typer._completion_classes import time: 646 | 646 | typer.models import time: 143 | 143 | typer.params import time: 36 | 36 | org import time: 7 | 43 | org.python import time: 8 | 51 | org.python.core import time: 98 | 148 | copy import time: 124 | 272 | typer.utils import time: 173 | 2127 | typer.completion import time: 907 | 907 | typer.core import time: 455 | 8870 | typer.main import time: 102 | 23699 | typer import time: 8 | 23706 | typer.main 

There is still a platform imported by uuid, but for some reason that is faster than having the import in main.py.

It takes a while to import platform, so use sys.platform to check for macOS/Linux, and only import platform to detect BSD dialects.
@svlandeg svlandeg added the feature New feature, enhancement or request label Oct 2, 2025
@svlandeg svlandeg self-assigned this Nov 4, 2025
@svlandeg svlandeg changed the title Import platform later ⚡️ Import platform only to determine BSD dialects Nov 4, 2025
Copy link
Member

@svlandeg svlandeg left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reviewed the changes in detail and they look good to me. I know that there are sometimes very subtle differences between platform.system() and sys.platform though - The former returning the OS that Python is running on, the latter for which the Python interpreter was built for. I'd expect the end result would typically be the same. But for a marginal performance gain, I'm not sure we want to take the risk to change existing, thoroughly tested code.

I'll leave the final decision with Tiangolo.

@svlandeg svlandeg removed their assignment Nov 4, 2025
@pjonsson
Copy link
Author

pjonsson commented Nov 4, 2025

My interest lies in the reduced import time, so if the platform semantics is preferred, I can move the import into the two functions that use it instead and keep the old test.

@svlandeg
Copy link
Member

@pjonsson: Sure, I think that may give the PR a higher chance of getting merged, as the changes would be more minimal & less risky. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature New feature, enhancement or request

2 participants