I've created a little Python app, and I want it to hide the console window in the middle of the process, so renaming it as .pyw won't solve the problem.
It would be best to have some kind of function to minimize the window, any thoughts?
On windows you may use win32api:
from win32 import win32api
from win32 import win32process
from win32 import win32gui
def callback(hwnd, pid):
if win32process.GetWindowThreadProcessId(hwnd)[1] == pid:
# hide window
win32gui.ShowWindow(hwnd, 0)
# find hwnd of parent process, which is the cmd.exe window
win32gui.EnumWindows(callback, os.getppid())
there is a good way to do it with cmd.
open command prompt:
start /min py -x path\test.py
replace your version of python by 'x' and replace 'path' by the real path of your python project. this may help you to never see the console.
you can start your program again in python like this:
import os
os.sysyem('start /min %~dp0test.py)
but I don't know the way to minimize the console in the middle of program.
Much simpler method is to rename the main python source file's extension from py to pyw. This signals python that no console is required and it is a window'ed script.
E.g. rename PythonApp.py to PythonApp.pyw
Haven't tested but should work on all platforms.
Related
I searched for a way to hide a python caused window, for example a console or a ui window, so that you can't even see the open tab from this running application.So its like all actions of the python-program never have happend.
For example you do this:
print("Hello World")
and the user souldn't see anything of this:
But I found nothing, so does anybody know how this works?
Change the file extension of your python script file to '.pyw'. So, rename asdf.py to asdf.pyw.
This will make your script to be interpreted by a different executable than normal (precisely, pythonw.exe instead of python.exe).
Note that I do not know whether this works on other operating systems than Windows.
I finally found out a way to do this by using two modules:
*This works for cmd- and GUI-windows
import win32console # first module
import win32gui # secound one
win = win32console.GetConsoleWindow()
win32gui.ShowWindow(win, 0) # Hides the window
win32gui.ShowWindow(win, 1) # Shows the window
Edit: I found a second way to hide a terminal windows that is caused py python: All you have to do is to install pyinstaller with pip(3). Then write your sript, go to the command prompt and type in:
pyinstaller --onefile -w <sriptname>
-w = don't shows any console window (windows-less)
I am writing an IRC bot in Python.
I wish to make stand-alone binaries for Linux and Windows of it. And mainly I wish that when the bot initiates, the console window should hide and the user should not be able to see the window.
What can I do for that?
Simply save it with a .pyw extension. This will prevent the console window from opening.
On Windows systems, there is no notion of an “executable mode”. The Python installer automatically associates .py files with python.exe so that a double-click on a Python file will run it as a script. The extension can also be .pyw, in that case, the console window that normally appears is suppressed.
Explanation at the bottom of section 2.2.2
In linux, just run it, no problem. In Windows, you want to use the pythonw executable.
Update
Okay, if I understand the question in the comments, you're asking how to make the command window in which you've started the bot from the command line go away afterwards?
UNIX (Linux)
$ nohup mypythonprog &
Windows
C:/> start pythonw mypythonprog
I think that's right. In any case, now you can close the terminal.
On Unix Systems (including GNU/Linux, macOS, and BSD)
Use nohup mypythonprog &, and you can close the terminal window without disrupting the process. You can also run exit if you are running in the cloud and don't want to leave a hanging shell process.
On Windows Systems
Save the program with a .pyw extension and now it will open with pythonw.exe. No shell window.
For example, if you have foo.py, you need to rename it to foo.pyw.
This will hide your console. Implement these lines in your code first to start hiding your console at first.
import win32gui, win32con
the_program_to_hide = win32gui.GetForegroundWindow()
win32gui.ShowWindow(the_program_to_hide , win32con.SW_HIDE)
Update May 2020 :
If you've got trouble on pip install win32con on Command Prompt, you can simply pip install pywin32.Then on your python script, execute import win32.lib.win32con as win32con instead of import win32con.
To show back your program again win32con.SW_SHOW works fine:
win32gui.ShowWindow(the_program_to_hide , win32con.SW_SHOW)
If all you want to do is run your Python Script on a windows computer that has the Python Interpreter installed, converting the extension of your saved script from '.py' to '.pyw' should do the trick.
But if you're using py2exe to convert your script into a standalone application that would run on any windows machine, you will need to make the following changes to your 'setup.py' file.
The following example is of a simple python-GUI made using Tkinter:
from distutils.core import setup
import py2exe
setup (console = ['tkinter_example.pyw'],
options = { 'py2exe' : {'packages':['Tkinter']}})
Change "console" in the code above to "windows"..
from distutils.core import setup
import py2exe
setup (windows = ['tkinter_example.pyw'],
options = { 'py2exe' : {'packages':['Tkinter']}})
This will only open the Tkinter generated GUI and no console window.
Some additional info. for situations that'll need the win32gui solution posted by Mohsen Haddadi earlier in this thread:
As of python 361, win32gui & win32con are not part of the python std library.
To use them, pywin32 package will need to be installed; now possible via pip.
More background info on pywin32 package is at: How to use the win32gui module with Python?.
Also, to apply discretion while closing a window so as to not inadvertently close any window in the foreground, the resolution could be extended along the lines of the following:
try :
import win32gui, win32con;
frgrnd_wndw = win32gui.GetForegroundWindow();
wndw_title = win32gui.GetWindowText(frgrnd_wndw);
if wndw_title.endswith("python.exe"):
win32gui.ShowWindow(frgrnd_wndw, win32con.SW_HIDE);
#endif
except :
pass
After writing the code you want to convert the file from .py to .exe, so possibly you will use pyinstaller and it is good to make exe file. So you can hide the console in this way:
pyinstaller --onefile main.py --windowed
I used to this way and it works.
just change the file extension from .py to .pyw
As another answer for all upcoming readers:
If you are using Visual Studio as IDE, you can set "Window Application" in the Project settings with a single checkmark. Which is working with py-extension as well.
a decorator factory for this (windows version, unix version should be easier via os.fork)
def deco_factory_daemon_subprocess(*, flag_env_var_name='__this_daemon_subprocess__', **kwargs_for_subprocess):
def deco(target):
#functools.wraps(target)
def tgt(*args, **kwargs):
if os.environ.get(flag_env_var_name) == __file__:
target(*args, **kwargs)
else:
os.environ[flag_env_var_name] = __file__
real_argv = psutil.Process(os.getpid()).cmdline()
exec_dir, exec_basename = path_split(real_argv[0])
if exec_basename.lower() == 'python.exe':
real_argv[0] = shutil.which('pythonw.exe')
kwargs = dict(env=os.environ, stdout=subprocess.PIPE, stderr=subprocess.PIPE, )
kwargs.update(kwargs_for_subprocess)
subprocess.Popen(real_argv, **kwargs)
return tgt
return deco
use it like this:
#deco_factory_daemon_subprocess()
def run():
...
def main():
run()
I have a .pyw script that works when I double click it etc and it stays open till I close it but I've added it to the registry to run at startup. It does run on startup but it doesn't stay open like its set to. It flashes the gui and then just closes.
Any ideas why this is happening or how to fix it?
P.S I don't want to create a shortcut in the startup folder linking to the .pyw file.
I added the my python script to the registry with another python script :p
import _winreg
aReg = _winreg.ConnectRegistry(None,_winreg.HKEY_LOCAL_MACHINE)
aKey = _winreg.OpenKey(aReg, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", 0, _winreg.KEY_WRITE)
_winreg.SetValueEx(aKey,"MyScript",0, _winreg.REG_SZ, myScript_path)
And when I browse that path in the registry:
HKEY_LOCAL_MACHINE > SOFTWARE > Microsoft > Windows > CurrentVersion > Run it is there with the correct path in data and type REG_SZ
There was a very strange error that only happened at startup since one of the processes the script seemed to use hadn't been started yet. Running as a .py with python.exe didn't produce the error, it only happened when the script was run as a .pyw so I wrote the sys.stdout to a file to log its progress and errors.
Before I had used the logging module but it didn't seem to give as much detail as just outputting straight to file.
After checking the file I was able to fix the code so essentially it was a code problem but quite a sneaky one.
My two cents:
had the same issue (.pyw in startup folder just flashed its gui then closed). Added a 'sleep' before the import commands and it worked. I believe the OS takes a little time to get ready for one/some import commands in my code.
#coding:utf-8
from time import sleep
sleep(20)
from Tkinter import *
from Tix import *
from time import strftime
import urllib
from itertools import izip_longest
import winsound
I have a tkinter script, which runs just fine in IDLE. However, when I double click the .py-file from Windows Explorer, the console window flashes half a second and then it exits.
I was able to screenprint the console window. It says:
...etc.etc...
NameError: global name 'simpledialog' is not defined
simpledialog is a module in tkinter which I use in my script. As I do from tkinter import *, there is no need to explicitly write tkinter.simpledialog.
It works in IDLE, why not as .py?
IDLE uses Tkinter as its graphical environment. It is possible that your code is relying on a side effect of an import by IDLE itself. This is especially true if you use IDLE without a subprocess.
The simpledialog module does not import when using from tkinter import *.
Try adding this to your code:
import tkinter.simpledialog as simpledialog
Have you updated your PATH environment variable so that your Python executable is found? You can find more information on how to do here - Using Python on Windows
But you basically need to make sure that the folder containing python.exe (e.g. C:\Python32) is displayed when you type the following command from a prompt:
echo %PATH%
I had exactly the same problem with one of my scripts utilizing Tkinter.
Adding call to mainloop() fixed the issue.
See this tutorial for an example: [http://sebsauvage.net/python/gui/#import1
In my case, in the init function I have
def __init__(self,Width=400, Height=400):
# Create GUI window ------------------------------
win = Tk()
...
in the end of init I added:
win.mainloop()
Now it works by just running the file.
Hope this helps
Similar trouble for me just now, in my first week with python. But I dimly remembered a similar problem with a simple early test script and thought the trouble then was # comments.
So I tried that with my Tkinter infused .py script. It ran fine in IDLE as you say, then only flashed when clicked in windows. But there were a couple # commented lines at the top of file.
I took them all out and it now runs no sweat directly in windows. Have a look .. for #.
Sorry, can't seem to delete this post. Now the files work #comments included. Don't know what's up with that. ..
I found that changing the executable py file to a file.pyw fixed the problem. This tells python to execute it using the pythonw.exe which runs the script without the terminal/console in the background.
Not sure why this works, perhaps some screwed up environment variables from a previous python installation.
Changing the file's extension to pyw instead of py might solve the problem
When I use IPython along with the -wthread option, it spawns a python subprocess, which appears as a Mac OS X application.
My problem is that when I send commands to that application (for example plotting with matplotlib), the window is updated behind all my other windows. I would like to be able to call a python command to switch this python window to the front (I do that manually with ⌘-tab, but I have to find the python application first, and there might be several ones).
Is there a python script to detect which application IPython has spawned, and how to then automatically switch to it in OS X?
(I'm stating the problem in OS X, but the issue should be similar on other systems).
Edit: let me break this down in two problems:
how to know which Mac OS X application python is running in? (probably possible with some IPython witchery)
how to tell Mac OS X to put the focus on that application? (maybe using applescript)
Could be either:
Making a new python script that tracks grandchild processes of another script might be tricky. The IPython documentation has an example to monitor spawned processes by pid; JobControl. JobControl only kills the processes but I imagine adding a command to change window focus would be fairly easy.
From what I've read, the Tk gui does not properly set window focus on macs. If your 'matplotlib' or otherwise uses the Tk gui, this may be the problem. -source-
I am not very familiar with OS X, so either run with those, clarify your situation or let me know if I'm too far off.
Here is my full solution, with an IPython magic function.
Install appscript (see this question about switching apps programmatically in OS X), and put the following code in a script called activate.py in your ~/.ipython folder.
import appscript
import sys
appscript.app(pid=int(sys.argv[1])).activate()
Now, edit your ~/.ipython/ipy_user_conf.py configuration file and define the magic function:
def wxactivate(self, arg):
import wx
pid = wx.GetProcessId()
ip = self.api
import os
here = os.path.dirname(__file__)
import subprocess
subprocess.Popen([os.path.join(here, 'activate.py'), str(pid)])
Now you just have to register this magic IPython function by putting the following somewhere in that same configuration file:
ip.expose_magic('wxactivate', wxactivate)
Now, after you run IPython -wthread, you can call %wxactivate and you will switch to the corresponding Python application!
(note that the reason why one has to run the call to appscript's activate() in another process in not clear to me; it may have to do with some threading problem... any explanation would be appreciatated)