obs-studio icon indicating copy to clipboard operation
obs-studio copied to clipboard

Python scripting 'stderr_logger' does not reimplement 'isatty'

Open vivi90 opened this issue 4 years ago • 3 comments

Operating System Info

Other

Other OS

Manjaro Linux, Kernel 5.12

OBS Studio Version

26.1.2

OBS Studio Version (Other)

No response

OBS Studio Log URL

None

OBS Studio Crash Log URL

Not crashed

Expected Behavior

Want to use the Python package youtube_dl inside my OBS Script.

Current Behavior

Throws a Python Error AttributeError: 'stderr_logger' object has no attribute 'isatty' in the Script Log window. See: https://github.com/ytdl-org/youtube-dl/issues/28914

Steps to Reproduce

  1. Create a simple script barebone.
  2. import youtube_dl package.
  3. Instantiate it by parser = youtube_dl.YoutubeDL(...).
  4. Call it by: parser.extract_info(...).

In contrast, running the following standalone example script outside of OBS wil NOT reproduce the issue:

#!/usr/bin/env python3
import youtube_dl as ydl

url = "https://www.youtube.com/watch?v=6qEzh3wKVJc"

with ydl.YoutubeDL(
    {
        "forcejson": True,
        "noplaylist": True,
        "format": "bestaudio"
    }
) as parser:
    meta = parser.extract_info(
        url,
        download=False
    )

print(meta['thumbnail'])
print(meta['title'])
print(meta['url'])

Anything else we should know?

Workaround: https://github.com/ytdl-org/youtube-dl/issues/28914#issuecomment-829739392

vivi90 avatar Apr 30 '21 11:04 vivi90

We reimplement the logger to be able to display it in our Script Log window.

https://github.com/obsproject/obs-studio/blob/e55bfa8e202894f84fe0d90e64ccca42f2a02d9a/deps/obs-scripting/obs-scripting-python.c#L32-L48

I have a feeling this is related.

WizardCM avatar Apr 30 '21 11:04 WizardCM

We reimplement the logger to be able to display it in our Script Log window.

https://github.com/obsproject/obs-studio/blob/e55bfa8e202894f84fe0d90e64ccca42f2a02d9a/deps/obs-scripting/obs-scripting-python.c#L32-L48

I have a feeling this is related.

Yes, your right. I also think this is the part, that needs to be modified. Please take also a look at: https://github.com/ytdl-org/youtube-dl/issues/16659 Maybe it's a weak but working solution to just replace:

sys.stderr = stderr_logger()\n"; 

with:

sys.stderr = stderr_logger()\n\
sys.stdout.isatty = lambda: False\n\
sys.stderr.isatty = lambda: False\n"; 

Edit:

Here is a much more better solution. Replace:

static const char *startup_script = "\n\
import sys\n\
import os\n\
import obspython\n\
class stdout_logger(object):\n\
	def write(self, message):\n\
		obspython.script_log_no_endl(obspython.LOG_INFO, message)\n\
	def flush(self):\n\
		pass\n\
class stderr_logger(object):\n\
	def write(self, message):\n\
		obspython.script_log_no_endl(obspython.LOG_ERROR, message)\n\
	def flush(self):\n\
		pass\n\
os.environ['PYTHONUNBUFFERED'] = '1'\n\
sys.stdout = stdout_logger()\n\
sys.stderr = stderr_logger()\n";

with:

static const char *startup_script = "\n\
import sys\n\
import os\n\
import obspython\n\
class stdout_logger(object):\n\
    def write(self, message):\n\
        obspython.script_log_no_endl(obspython.LOG_INFO, message)\n\
    def flush(self):\n\
        pass\n\
    def isatty(self):\n\
        return False\n\
class stderr_logger(object):\n\
    def write(self, message):\n\
        obspython.script_log_no_endl(obspython.LOG_ERROR, message)\n\
    def flush(self):\n\
        pass\n\
    def isatty(self):\n\
        return False\n\
os.environ['PYTHONUNBUFFERED'] = '1'\n\
sys.stdout = stdout_logger()\n\
sys.stderr = stderr_logger()\n";

The background of this, by the way: The isatty() method is used to determine, if the output goes to a real terminal (True) or is just redirected or piped (False).

But again: I am just too lazy to compile and test it at the moment^^

vivi90 avatar Apr 30 '21 11:04 vivi90

Same error with the speedtest module. Had to remove the check from the module. Works just as fine...

Nama avatar Jan 08 '23 18:01 Nama