Skip to content

Conversation

@bastimeyer
Copy link
Member

Follow-up of #6142

This fixes the case where sys.stdout is None, when the Python process doesn't have the stdout file descriptor (fd1). This can be forced in BASH for example, by appending >&-.

import pathlib,os,sys
pid = str(os.getpid())
fd1 = pathlib.Path("/proc", pid, "fd", "1")
sys.stderr.write(f"{pid=}\n{sys.stdout is None=}\n{fd1.readlink() if fd1.exists() else None=}\n")
$ python <<< "${CODE}"
pid='318408'
sys.stdout is None=False
fd1.readlink() if fd1.exists() else None=PosixPath('/dev/pts/2')
$ python <<< "${CODE}" >&-
pid='318428'
sys.stdout is None=True
fd1.readlink() if fd1.exists() else None=None

Currently on master, this results in an AttributeError, as the streamlink_cli.compat module assigns its stdout attribute to sys.stdout.buffer, the binary output stream used for writing stream content to stdout (e.g. --stdout).

So when fd1 is missing and sys.stdout is None, we need a fallback stream. Simply use a devnull output stream in this case (and close it on exit).

When stdout is missing, the logging stream and console output stream will automatically be stderr.


master

$ streamlink >&-
Traceback (most recent call last):
  File "/home/basti/venv/streamlink-312/bin/streamlink", line 5, in <module>
    from streamlink_cli.main import main
  File "/home/basti/repos/streamlink/src/streamlink_cli/main.py", line 25, in <module>
    from streamlink_cli.argparser import ArgumentParser, build_parser, setup_session_options
  File "/home/basti/repos/streamlink/src/streamlink_cli/argparser.py", line 13, in <module>
    from streamlink_cli.constants import STREAM_PASSTHROUGH
  File "/home/basti/repos/streamlink/src/streamlink_cli/constants.py", line 7, in <module>
    from streamlink_cli.compat import DeprecatedPath
  File "/home/basti/repos/streamlink/src/streamlink_cli/compat.py", line 6, in <module>
    stdout: BinaryIO = sys.stdout.buffer
                       ^^^^^^^^^^^^^^^^^
AttributeError: 'NoneType' object has no attribute 'buffer'

PR

$ streamlink >&-
usage: streamlink [OPTIONS] <URL> [STREAM]

Use -h/--help to see the available options or read the manual at https://streamlink.github.io
$ streamlink --stdout httpstream://file:///dev/zero best >&-
[cli][info] Found matching plugin http for URL httpstream://file:///dev/zero
[cli][info] Available streams: live (worst, best)
[cli][info] Opening stream: live (http)
^C[cli][info] Stream ended
Interrupted! Exiting...
[cli][info] Closing currently open stream...

Removing stderr as well is currently unsupported, and the process will stop because of a failure of the logging / console output setup, which falls back to stderr if stdout is None. Maybe I'll have a look at this later, too.

$ streamlink >&- 2>&-; echo $?
1

@bastimeyer bastimeyer force-pushed the cli/missing-stdout-fallback branch from 3cf5eb0 to 819b581 Compare September 23, 2024 22:54
@bastimeyer bastimeyer force-pushed the cli/missing-stdout-fallback branch from 819b581 to 633aa8f Compare September 23, 2024 23:09
@bastimeyer
Copy link
Member Author

No stdout/stderr

$ streamlink >&- 2>&-; echo $?
0
$ streamlink -l debug --logfile /tmp/log >&- 2>&- && cat /tmp/log
[cli][debug] OS:         Linux-6.11.0-1-git-x86_64-with-glibc2.40
[cli][debug] Python:     3.12.6
[cli][debug] OpenSSL:    OpenSSL 3.3.2 3 Sep 2024
[cli][debug] Streamlink: 6.10.0+34.g633aa8f4
[cli][debug] Dependencies:
[cli][debug]  certifi: 2024.8.30
[cli][debug]  isodate: 0.6.1
[cli][debug]  lxml: 5.3.0
[cli][debug]  pycountry: 24.6.1
[cli][debug]  pycryptodome: 3.20.0
[cli][debug]  PySocks: 1.7.1
[cli][debug]  requests: 2.32.3
[cli][debug]  trio: 0.26.2
[cli][debug]  trio-websocket: 0.12.0.dev0
[cli][debug]  typing-extensions: 4.12.2
[cli][debug]  urllib3: 2.2.3
[cli][debug]  websocket-client: 1.8.0
[cli][debug] Arguments:
[cli][debug]  --loglevel=debug
[cli][debug]  --logfile=/tmp/log
[cli][debug]  --player=/usr/bin/mpv
[cli][debug]  --webbrowser-headless=True
usage: streamlink [OPTIONS] <URL> [STREAM]

Use -h/--help to see the available options or read the manual at https://streamlink.github.io
$ streamlink -o /tmp/foo -f --hls-duration=10 URL best >&- 2>&- \
  && ffprobe -v error -of json -show_streams /tmp/foo | jq -r ".streams[0].duration"
9.984567

@bastimeyer bastimeyer marked this pull request as ready for review September 23, 2024 23:13
@bastimeyer bastimeyer merged commit 65d49fb into streamlink:master Sep 23, 2024
@bastimeyer bastimeyer deleted the cli/missing-stdout-fallback branch September 23, 2024 23:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant