Hiding the console while executing a script on Windows
The way I've done it on Windows 7 is by making a shortcut (or link) that runs my script with the pythonw.exe
interpreter, which has no console, instead of the default python.exe
.
Just follow these 3 steps:
- First create a normal shortcut to your script. One way to do this is to drag the icon for the script file shown in an Explorer window to where you want the shortcut to be (like the desktop) and hold down the Alt key when releasing the mouse button.
- Right-click on the just created shortcut and select
Properties
from the the menu that pops-up. - A Properties dialog for the shortcut will appear. In it insert
C:\python27\pythonw.exe
and a space before the path to the your script file. if the path to your script has any spaces in it, it must now be enclosed in double quotes._ If you're using another version of Python, you'll also need to change thePython27
accordingly.
i.e. A target of D:\path with spaces in it to\myscript.py
would need to be changed
to C:\Python27\pythonw.exe "D:\path with spaces in it to\myscript.py"
You can also change the shortcut's icon here if you wish.
Here's an example:
Update - simpler way: You can also change the extension of your script to .pyw
which will cause it to be run with the pythonw.exe
instead of the python.exe
.
hide console with executing python script
pass -w or --windowed or --noconsole flag to hide console.
Try GUI pyinstaller by installing auto py to exe. It makes you more easier to compile your script.
pip install auto-py-to-exe
How to hide the console window while starting Tkinter applications but reopening it when the GUI button is pressed to run the python script?
Hiding an existing console window isn't a good idea in general. It's a shared resource, and if your application dies with the window hidden, it's basically rendering useless every other application that's attached to the console.
You can run your script via pythonw.exe, which doesn't automatically allocate or attach to a console. Then allocate your own console on demand, switch to full-screen mode (if supported), set the window title, and rebind sys.std*
to the console device files "CONIN$" and "CONOUT$". You have sole ownership of this window, so you're entitled to hide it.
For example:
import os
import sys
import time
import ctypes
import platform
try:
import Tkinter as tk
except ImportError:
import tkinter as tk
from ctypes import wintypes
user32 = ctypes.WinDLL('user32', use_last_error=True)
kernel32 = ctypes.WinDLL('kernel32', use_last_error=True)
_windows_version = tuple(map(int, platform.version().split('.')))
kernel32.GetConsoleWindow.restype = wintypes.HWND
user32.SendMessageW.argtypes = (wintypes.HWND, wintypes.UINT,
wintypes.WPARAM, wintypes.LPARAM)
user32.ShowWindow.argtypes = (wintypes.HWND, ctypes.c_int)
SW_HIDE = 0
SW_MAXIMIZE = 3
SW_SHOW = 5
WM_SYSKEYDOWN = 0x0104
VK_RETURN = 0x0D
def toggle_fullscreen(hwnd=None):
if _windows_version < (10, 0, 14393):
return
if hwnd is None:
hwnd = kernel32.GetConsoleWindow()
lparm = (user32.MapVirtualKeyW(VK_RETURN, 0) << 16) | 0x20000001
user32.SendMessageW(hwnd, WM_SYSKEYDOWN, VK_RETURN, lparm)
def printf(s):
for c in s:
sys.stdout.write('%s' % c)
sys.stdout.flush()
time.sleep(0.15)
def input(s):
sys.stdout.write(s)
sys.stdout.flush()
return sys.stdin.readline().rstrip('\n')
def hello():
kernel32.SetConsoleTitleW(u"Hello, World!")
printf('Hello, World!')
input('\nPress enter to continue...')
class App(object):
allocated_console = None
def __init__(self):
if self.allocated_console is None:
# one-time set up for all instances
allocated = bool(kernel32.AllocConsole())
App.allocated_console = allocated
if allocated:
hwnd = kernel32.GetConsoleWindow()
user32.ShowWindow(hwnd, SW_HIDE)
toggle_fullscreen(hwnd)
self.root = root = tk.Tk()
nvar = tk.StringVar(root)
en = tk.Entry(textvariable=nvar)
en.pack()
btn = tk.Button(text="Shell", command=self.runshell)
btn.pack()
def mainloop(self):
self.root.mainloop()
def runshell(self):
hwnd = kernel32.GetConsoleWindow()
user32.ShowWindow(hwnd, SW_SHOW)
try:
old_title = ctypes.create_unicode_buffer(512)
n = kernel32.GetConsoleTitleW(old_title, 512)
if n > 512:
old_title = ctypes.create_unicode_buffer(n)
kernel32.GetConsoleTitleW(old_title, n)
old_stdin = sys.stdin
old_stderr = sys.stderr
old_stdout = sys.stdout
try:
with open('CONIN$', 'r') as sys.stdin,\
open('CONOUT$', 'w') as sys.stdout,\
open('CONOUT$', 'w', buffering=1) as sys.stderr:
self.root.destroy()
hello()
finally:
kernel32.SetConsoleTitleW(old_title)
sys.stderr = old_stderr
sys.stdout = old_stdout
sys.stdin = old_stdin
finally:
if self.allocated_console:
user32.ShowWindow(hwnd, SW_HIDE)
if __name__ == '__main__':
for i in range(3):
app = App()
app.mainloop()
pythonw.exe is typically associated with the .pyw file extension. You can also configure tools such as py2exe to create a non-console executable.
I had to write an input
function since raw_input
writes its prompt to the stderr
FILE
stream. I'd rather avoid rebinding C standard I/O from Python.
It toggles full-screen mode for an allocated console in Windows 10 by sending the key combination Alt+Enter to the console window using a WM_SYSKEYDOW
message. Full-screen mode isn't supported in Windows Vista up to Windows 8. In that case you could maximize the window and resize the screen buffer.
Note that I'm only hiding the allocated console window. Avoid calling FreeConsole
. The C runtime's conio API (e.g. kbhit
, getch
) caches a handle to "CONIN$", but it provides no dynamically exported and supported way to reset this cached handle. These CRT functions weren't designed to support cycling over multiple consoles. The assumption is that a process is attached to at most one console for its lifetime. At least in Windows 10 this cached handle also prevents the unused console host process from destroying its window and exiting until your process exits.
If the user closes the console while the application is attached, the console will kill the application. This cannot be prevented. At best you can set a control handler to be notified that process is about to be killed.
Another approach to check whether you can hide the console window would be to call GetConsoleProcessList
to get the list of attached processes. You're entitled to hide the window if your process is the only one. If there are two processes attached, it seems reasonable to hide the window if the other one is the py[w].exe launcher that Python 3 installs. Checking the latter requires opening a handle to the process via OpenProcess
to get the image name via GetModuleBaseName
.
Related Topics
How to Add Property to a Class Dynamically
Shared-Memory Objects in Multiprocessing
Pandas: Filter Rows of Dataframe with Operator Chaining
Why Does the Print Function Return None
Insert Line at Middle of File with Python
Slicing a List in Python Without Generating a Copy
Pandas Long to Wide Reshape, by Two Variables
Setup Script Exited with Error: Command 'X86_64-Linux-Gnu-Gcc' Failed with Exit Status 1
How to Print Original Variable's Name in Python After It Was Returned from a Function
Hash Function in Python 3.3 Returns Different Results Between Sessions
How to Use a Dll File from Python
How to Convert SQLalchemy Row Object to a Python Dict
Pygame.Event.Get() Not Returning Any Events When Inside a Thread
Efficient String Matching in Apache Spark