python / python/cpython

`sys.ps1`/`sys.ps2` should be empty (or not shown) if stdin is not a tty

Open
#93,139 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

stdlib type-bug
Dominant language
Python
Stars
77.2k
Forks
36k
PR merge metrics
PR metrics pending

Description

Bug report

This straddles the line between bug report and feature request.

I've searched for related issues or PRs but I wasn't able to find anything directly related. I'm sorry if this has been raised and discussed before.

Normally, if stdin is not a TTY, then python3 tries to read a script from stdin, terminating with EOF, and then runs the script. This effectively means that the script itself can't read more stdin, because EOF was already sent. A way to work around this is to use python3 -i, which then causes the interpreter to behave more like the POSIX shell, evaluating commands as it receives them.

The commandline parameter -i is documented:

When a script is passed as first argument or the -c option is used, enter interactive mode after executing the script or the command.

The scenario that python3 -i may be run without other flags isn't mentioned, but it works.

In particular, this mechanism gives me a really nice way to connect to a host with ssh, inject a script (via stdin), and then run it and interact with it. I could do the same with an extremely large -c parameter, but I'd prefer not to spam the output of ps with a gigantic script, if possible[^1].

This is all already working wonderfully. There is one strange issue, though: possibly as a side effect of #46221, on the stderr I get a whole lot of output looking like:

>>> >>> >>> >>> >>> >>> >>> >>> ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... >>> >>> 

This is, of course sys.ps1 and sys.ps2 being displayed for each line in my script. First a bunch of imports (ps1), then a block defining a class (sys.ps2), then the lines to instantiate and execute a method in that class (more sys.ps1).

I don't want to simply redirect stderr to /dev/null because my script (or the Python interpreter, in case of exceptions) could produce error output and I'd like to receive it.

There are a few other ways that I could hack around this. Something ugly like:

python3 -ic '"cockpit-bridge"; __import__('sys').ps1=""'

would do the trick (and is probably what I'll do for now), but it would be nice if this wasn't necessary.

So the ask is simple: in the case that stdin is not a tty, then sys.ps1 and sys.ps2 should either be set to empty, or not shown.

I tested a couple of POSIX shells (bash, dash) for comparison and each of them seems to do both. Specifically, when reading from a non-tty, $PS1 is unset, and is also ignored, even if I do set it to something.

Here's a simple reproducer:

sh$ python3 -qi <<EOF
print('x')
print('y')
print('z')
EOF
>>> x
>>> y
>>> z
>>> 

You can see that the prompts are going on stderr by redirecting:

bash-5.1$ python3 -qi 2>/dev/null <<EOF
> print('x')
> print('y')
> print('z')
> EOF
x
y
z

The output I'd like to see looks like:

# NB: This is not currently possible
sh$ python3 -qi <<EOF
print('x')
print('y')
print('z')
EOF
x
y
z

Your environment

Python 3.10.3 (main, Mar 18 2022, 00:00:00) [GCC 12.0.1 20220308 (Red Hat 12.0.1-0)] on linux

aka python3-3.10.3-1.fc36.x86_64.

[^1]: indeed, I intend to (ab)use -c to display the name of the script, using an (ignored) string literal like so:

`ssh somehost python3 -ic '"cockpit-bridge"'`

Using `-c` like this also means that the interactive banner gets suppressed, which means that I don't need to specify `-q` to do that.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by running the heredoc reproducer with python3 -qi and observe prompts written to stderr while stdin is not a TTY. Trace the interactive input and prompt handling around sys.ps1 and sys.ps2; done means prompts are empty or suppressed for non-TTY stdin while normal interactive TTY behavior and error output remain intact.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.