pythonuser-interfacetkinterexecutablemoviepy

Python executable not working if console is hidden, using Tkinter GUI


I have a Python 3.8.0 program that downloads videos from YouTube, extracts their audio and creates an mp3, all this with a Tkinter interface. The program works perfect from VScode. I made it into an executable with the command 'pyinstaller --onefile code.py'; the GUI and the console appear, and it works.

Now if I add '-w' to create an executable with no console, just GUI, the program fails. The exception is: 'NoneType' object has no attribute 'write' and happenns in the next lines:

absolute_route = os.path.abspath(routemp4)
video = VideoFileClip(absolute_route)
routemp3 = absolute_route[:len(absolute_route)-4] + ".mp3"
video.audio.write_audiofile(routemp3)

' routemp4 is the path of an mp4 file taken with 'youtubeObject.default_filename', is valid and has audio (again, the exact same code works with the console open).

I figured it might be the paths, as if the console is closed the GUI program might have troubles, but I added absolute paths and nothing changed.

The code works just fine if the console is open but fails if it is just the GUI. There is a similar stackoverflow question but it was solved since the guy´s video had no audio, which is not my case. My problem lays within the GUI and console. Thank you in advance.


Solution

  • When Python is started without a console, sys.stdout will be set to None. This is mentioned in the docs for the sys module.

    Presumably something is calling sys.stdout.write, which would cause the error you're seeing.

    As mentioned in an answer to a related question, if you can change the code to call print instead of sys.stdout.write, then this will be handled for you (i.e. nothing will be printed and no error will be raised).

    If you can't change whatever code is calling sys.stdout.write, then, as suggested in an answer to a different related question, you could set sys.stdout (at the start of your program) to a file object that does nothing:

    import sys, os
    if sys.stdout is None:
        sys.stdout = open(os.devnull, "w")
    

    That should get rid of the error. If not, try doing the same for sys.stderr in addition to sys.stdout, in case something is trying to write to the standard error stream.