How to avoid console window with .pyw file containing os.system call?

You should use subprocess.Popen class passing as startupinfo parameter's value instance of subprocess.STARTUPINFO class with dwFlags attribute holding subprocess.STARTF_USESHOWWINDOW flag and wShowWindow attribute holding subprocess.SW_HIDE flag. This can be inferred from reading lines 866-868 of subprocess.py source code. It might be necessary to also pass subprocess.CREATE_NEW_CONSOLE flag as a value of creationflags parameter as you run under pythonw.exe which does not open a console.

When you use shell=True it just happens that all of the above is set correctly but that doesn't mean it's a proper solution. I would argue it's not because it adds overhead of running command interpreter and parsing arguments. In addition you should keep in mind that (...) the use of shell=True is strongly discouraged in cases where the command string is constructed from external input according to documentation of subprocess module.


The solution that Piotr describes is actually not as complicated as it may sound. Here is an example where a startupinfo is passed to a check_call invocation to suppress the console window:

startupinfo = subprocess.STARTUPINFO()
startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW

subprocess.check_call(cmd, startupinfo=startupinfo)

Since the convenience functions call, check_call, and check_output forward their **kwargs to the Popen constructor, it is not required to use Popen directly.