Skip to content

Commit 158367b

Browse files
authored
Improve responsiveness when invoked via Python (astral-sh#9315)
This saves a handful of milliseconds on Windows and even more on other platforms when running `python -m ruff`. On non-Windows systems the process is replaced directly (impossible on Windows unfortunately). ``` ❯ docker run --rm python:3.11 bash -c "for i in {1..15}; do python -m timeit -n 1 -r 1 'from pathlib import Path'; done" 1 loop, best of 1: 25.7 msec per loop 1 loop, best of 1: 3.07 msec per loop 1 loop, best of 1: 3.16 msec per loop 1 loop, best of 1: 3.06 msec per loop 1 loop, best of 1: 3.32 msec per loop 1 loop, best of 1: 3.93 msec per loop 1 loop, best of 1: 3.26 msec per loop 1 loop, best of 1: 3.73 msec per loop 1 loop, best of 1: 3.1 msec per loop 1 loop, best of 1: 3.29 msec per loop 1 loop, best of 1: 3.12 msec per loop 1 loop, best of 1: 3.05 msec per loop 1 loop, best of 1: 3.04 msec per loop 1 loop, best of 1: 3.19 msec per loop 1 loop, best of 1: 3.04 msec per loop ❯ docker run --rm python:3.11 bash -c "for i in {1..15}; do python -m timeit -n 1 -r 1 'import subprocess'; done" 1 loop, best of 1: 31.2 msec per loop 1 loop, best of 1: 3.75 msec per loop 1 loop, best of 1: 4.71 msec per loop 1 loop, best of 1: 3.88 msec per loop 1 loop, best of 1: 4.08 msec per loop 1 loop, best of 1: 4.35 msec per loop 1 loop, best of 1: 3.94 msec per loop 1 loop, best of 1: 4.06 msec per loop 1 loop, best of 1: 3.88 msec per loop 1 loop, best of 1: 3.85 msec per loop 1 loop, best of 1: 3.84 msec per loop 1 loop, best of 1: 4.01 msec per loop 1 loop, best of 1: 4.21 msec per loop 1 loop, best of 1: 4.07 msec per loop 1 loop, best of 1: 4.11 msec per loop ❯ python -m timeit -n 1 -r 1 "from pathlib import Path" 1 loop, best of 1: 5.25 msec per loop ❯ python -m timeit -n 1 -r 1 "import subprocess" 1 loop, best of 1: 7.61 msec per loop ```
1 parent 48e04cc commit 158367b

1 file changed

Lines changed: 12 additions & 11 deletions

File tree

python/ruff/__main__.py

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
11
import os
2-
import subprocess
32
import sys
43
import sysconfig
5-
from pathlib import Path
64

75

8-
def find_ruff_bin() -> Path:
6+
def find_ruff_bin() -> str:
97
"""Return the ruff binary path."""
108

119
ruff_exe = "ruff" + sysconfig.get_config_var("EXE")
1210

13-
path = Path(sysconfig.get_path("scripts")) / ruff_exe
14-
if path.is_file():
11+
path = os.path.join(sysconfig.get_path("scripts"), ruff_exe)
12+
if os.path.isfile(path):
1513
return path
1614

1715
if sys.version_info >= (3, 10):
@@ -23,16 +21,19 @@ def find_ruff_bin() -> Path:
2321
else:
2422
user_scheme = "posix_user"
2523

26-
path = Path(sysconfig.get_path("scripts", scheme=user_scheme)) / ruff_exe
24+
path = os.path.join(sysconfig.get_path("scripts", scheme=user_scheme), ruff_exe)
2725
if path.is_file():
2826
return path
2927

3028
raise FileNotFoundError(path)
3129

3230

3331
if __name__ == "__main__":
34-
ruff = find_ruff_bin()
35-
# Passing a path-like to `subprocess.run()` on windows is only supported in 3.8+,
36-
# but we also support 3.7
37-
completed_process = subprocess.run([os.fsdecode(ruff), *sys.argv[1:]])
38-
sys.exit(completed_process.returncode)
32+
ruff = os.fsdecode(find_ruff_bin())
33+
if sys.platform == "win32":
34+
import subprocess
35+
36+
completed_process = subprocess.run([ruff, *sys.argv[1:]])
37+
sys.exit(completed_process.returncode)
38+
else:
39+
os.execvp(ruff, [ruff, *sys.argv[1:]])

0 commit comments

Comments
 (0)