diff --git a/spacy/cli/project/run.py b/spacy/cli/project/run.py index 5289add36..bfd930766 100644 --- a/spacy/cli/project/run.py +++ b/spacy/cli/project/run.py @@ -176,7 +176,6 @@ def run_commands( """ for c in commands: command: Union[str, List[str]] - exe: Optional[str] = None if is_windows: command = c @@ -184,17 +183,18 @@ def run_commands( # cases. It will work in ordinary cases, but will miss cases where # the command is like: # "C:\My Programs\python.exe" script.py + # In a "missed" case the command will simply be executed unchanged. head, _, tail = c.partition(" ") - # This doesn't rewrite the command to include sys.executable - # because sys.executable might include spaces, quotes, or - # something, and need quoting itself. Instead the exe param is used - # to directly specify the binary to call. + # Actual Windows quoting is more complicated, but simpler quoting + # rules are used for the first argument in command invocations. + # + # https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-command-line-arguments + quoted_exe = f'"{sys.executable}"' if head in ("python", "python3"): - exe = sys.executable + command = f"{quoted_exe} {tail}" if head in ("pip", "pip3"): - exe = sys.executable - command = "python -m pip " + tail + command = f"{quoted_exe} -m pip {tail}" if not silent: print(f"Running command: {command}") @@ -215,7 +215,7 @@ def run_commands( print(f"Running command: {c}") if not dry: - run_command(command, capture=capture, exe=exe) + run_command(command, capture=capture) def validate_subcommand( diff --git a/spacy/util.py b/spacy/util.py index c526f796c..7ce708651 100644 --- a/spacy/util.py +++ b/spacy/util.py @@ -944,7 +944,6 @@ def run_command( *, stdin: Optional[Any] = None, capture: bool = False, - exe: Optional[str] = None, ) -> subprocess.CompletedProcess: """Run a command on the command line as a subprocess. If the subprocess returns a non-zero exit code, a system exit is performed. @@ -956,8 +955,6 @@ def run_command( sys.exit will be called with the return code. You should use capture=False when you want to turn over execution to the command, and capture=True when you want to run the command more like a function. - exe (Optional[str]): Path to Python executable to use. Passed separately - from the command on Windows to avoid quoting issues. RETURNS (Optional[CompletedProcess]): The process object. """ @@ -996,7 +993,6 @@ def run_command( input=stdin, encoding="utf8", check=False, - executable=exe, stdout=subprocess.PIPE if capture else None, stderr=subprocess.STDOUT if capture else None, )