Home / Alt manpages / python3.12(1)

  • python3.12(1)
  • User command
  • linux

Run Python 3.12 Scripts Safely from the Command Line

Python 3.12 on the command line looks simple until a script imports the wrong module because of where you happened to run it from. This guide builds a small, repeatable workflow: check the interpreter, run a script, pass arguments, execute a module, and feed code through standard input. You will also know when the current directory can affect imports and when isolated mode is the safer choice.

Allow about 15 minutes. You need a shell and a Python 3.12 installation. The examples use the interpreter installed here as Python 3.12.3 from the Ubuntu packages python3-minimal and python3.12-minimal. No root privileges are needed; run everything as an ordinary user unless your own script has a separate reason to need elevation.

1. Check which interpreter will run

Start with the executable name rather than assuming python means the version you want. This is a read-only check:

$ command -v python3.12
/usr/bin/python3.12
$ python3.12 --version
Python 3.12.3
$ dpkg-query -W -f='${Package} ${Version}\n' python3-minimal python3.12-minimal
python3-minimal 3.12.3-0ubuntu2.1
python3.12-minimal 3.12.3-1ubuntu0.17

The -V and --version options print the version and exit. Run this checkpoint before debugging a script that behaves differently on another host.

2. Run a script and pass arguments

Give a trusted script's path as the first non-option argument. Python places the script name in sys.argv[0] and later command-line words in sys.argv[1:]. Try it with a harmless throwaway script:

$ mkdir -p /tmp/python312-cli
$ printf '%s\n' 'import sys' 'print(sys.argv)' > /tmp/python312-cli/show_args.py
$ python3.12 /tmp/python312-cli/show_args.py alpha 'two words'
['/tmp/python312-cli/show_args.py', 'alpha', 'two words']
  • Quote an argument when the shell should pass spaces or wildcard characters literally.
  • Never paste an untrusted value into a shell command as if it were code. The shell parses the command first, then Python only ever receives the resulting arguments.

Checkpoint

A script run normally has its own directory placed at the front of sys.path. That makes local imports convenient, but it also means a file sitting beside the script can shadow a standard or third-party module. Keep scripts and working directories under your control.

3. Run a short command with -c

Use -c for a small expression or a few statements. The option ends Python's own option list, so later words become arguments to the command:

$ python3.12 -c 'import sys; print(sys.argv)' first second
['-c', 'first', 'second']
$ python3.12 -c 'print(6 * 7)'
42

Shell quoting matters here. Single quotes keep the shell from expanding characters inside the Python command. If the command contains a literal single quote, use a different quoting approach or put the code in a file instead: anything longer than a quick check is easier to review and repeat as a script.

Because -c adds the current directory to the start of sys.path, do not use it from an untrusted directory with an unexpected module name lying around. That is an import lookup issue, not a Python syntax error.

4. Execute a library module with -m

-m searches sys.path for a module and runs it as a program. Give a module name, not a filename ending in .py. The standard library's timeit module gives a safe example:

$ python3.12 -m timeit -n 1 -r 1 '1 + 1'
1 loop, best of 1: ... nsec per loop

The exact timing varies with the machine, so the useful check is that the command reports a loop count and exits successfully. Ask a module for its own options where it supports them:

$ python3.12 -m timeit -h | sed -n '1,8p'
Tool for measuring execution time of small code snippets.

This module avoids a number of common traps for measuring execution times.
See also the timeit() function in the timeit module.

Put the module name before its module-specific arguments. An option meant for Python itself must come first, while anything after -m MODULE belongs to that module.

5. Feed a program through standard input

A single hyphen tells Python to read the program from standard input, which is handy for a short pipeline or for testing how a program handles input separately from its source:

$ printf '%s\n' 'print(6 * 7)' | python3.12 -
42
$ printf '%s\n' 'import sys; print(sys.argv[0])' | python3.12 -
-

Do not confuse the program stream with data read by input() or sys.stdin: when Python is using standard input as its source, that stream is consumed as code. If the code itself must read data too, use a script file and redirect or pipe data to it instead.

An interactive terminal with no script, command or redirected input starts the interpreter prompt. Finish the session with exit() or the end-of-file key sequence for your shell. The primary prompt is normally >>> and the continuation prompt is ....

6. Reduce import surprises with -P or -I

Python normally prepends a potentially unsafe path to sys.path: the script directory for a file, or an entry representing the current directory for -c and the interactive interpreter. Python 3.12 gives you two controls for that:

  • -P stops that unsafe path being prepended, while leaving other environment settings in place.
  • -I enables isolated mode. It implies -E, -P and -s, so Python ignores PYTHON* environment variables, omits the script directory, and omits the user site-packages directory.

Check the difference without importing any local file:

$ python3.12 -I -c 'import sys; print(sys.flags.isolated); print(sys.path[0] == "")'
1
False

Use isolated mode when running a script supplied by another party, or when a build and test command must not inherit the operator's Python configuration.

Warning

Isolated mode is not a sandbox. The script still has the operating system permissions of the account running it. Do not run untrusted code with sudo or as a service account merely because -I is present.

7. Inspect environment and diagnostics

The interpreter can explain its own command-line and environment settings without running a script:

$ python3.12 --help-env
$ python3.12 --help-xoptions
$ python3.12 --help-all

Two settings worth knowing: PYTHONPATH augments module search locations, and PYTHONSTARTUP runs a readable file before an interactive prompt. Both are convenient on a personal machine but can make a command depend on hidden state. Use -E to ignore PYTHON* environment variables, or -I when you also need the path and user-site restrictions.

If imports are unclear, -v prints module initialisation and lookup information; it can be very noisy, so redirect it to a temporary file or inspect only a short command. For a live program, -X importtime reports import timing. Treat it as diagnostic output, not a performance guarantee.

Done means

  • You confirmed the executable and installed Python 3.12 version.
  • You can run a file, pass quoted arguments, use -c, use -m, and read source from standard input.
  • You understand that the current or script directory can affect imports.
  • You can choose -P, -E or -I when hidden environment and path entries are undesirable.
  • You kept the examples read-only apart from temporary files under /tmp.