103

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?

nbro
  • 15,395
  • 32
  • 113
  • 196

10 Answers10

172

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

Wolf
  • 9,679
  • 7
  • 62
  • 108
mdec
  • 5,122
  • 4
  • 25
  • 26
50

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.

Community
  • 1
  • 1
Charlie Martin
  • 110,348
  • 25
  • 193
  • 263
  • 1
    Thats not the main issue ... The main issue is to hide the console window then the program is running. How do it do that ? –  Apr 19 '09 at 01:47
  • You mean the one you're starting it from? – Charlie Martin Apr 19 '09 at 01:52
  • 2
    Change file extension to .pyw to associate with pythonw.exe http://oreilly.com/catalog/pythonwin32/chapter/ch20.html – mechanical_meat Apr 19 '09 at 01:52
  • "nohup mypythonprog &" will help me in linux ... but python is not gonna be installed on the windows machine. So "start pythonw mypythonprog" wont help me i guess. –  Apr 19 '09 at 02:42
  • okay, if puython isn't installed, you've got another problem. You want py2exe to build a standalone executable. http://logix4u.net/Python/Tutorials/How_to_create_Windows_executable_exe_from_Python_script.html and http://www.py2exe.org/index.cgi/FrontPage – Charlie Martin Apr 19 '09 at 03:58
  • unix ≠ Linux, unix ≠ UNIX, the above solution works for macOS and BSD also (they're unix), no code formatting. – noɥʇʎԀʎzɐɹƆ Jan 16 '17 at 18:39
  • 2
    Oh, I understand. Actually unix == UNIX and don't harass your elders. – Charlie Martin Jan 16 '17 at 19:00
29

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.

noɥʇʎԀʎzɐɹƆ
  • 9,967
  • 2
  • 50
  • 67
27

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)
Mohsen Haddadi
  • 1,296
  • 2
  • 16
  • 20
12

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.

John918
  • 165
  • 1
  • 9
  • Though I feel that this answer is a little off topic for the question, I went ahead and posted it anyway since it answers the following question (the link below) which was marked as a duplicate of this question. – John918 Nov 25 '16 at 04:44
  • http://stackoverflow.com/questions/31501769/how-to-remove-black-terminal-while-running-my-my-executable-file-in-tkinter-for – John918 Nov 25 '16 at 04:44
  • I'm actually using pyinstaller but that has an option for the same thing (-w) and fixed the problem for me. – ChrisWue Apr 11 '18 at 04:35
6

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
Snidhi Sofpro
  • 479
  • 7
  • 10
  • Why not just use the extension *.pyw? This is excessively long. – Anonymous Apr 25 '18 at 22:16
  • 2
    Using the .pyw extension might not be a solution in use cases such as with a Cgi server (http.server) on localhost. Because, in such cases, the python script ends up getting executed by python.exe despite the .pyw extension. – Snidhi Sofpro Apr 26 '18 at 14:47
  • The terminal will briefly pop up when running this though. – Xantium May 18 '18 at 22:05
  • Ah, but what if you did something like this: `import os,sys` `if sys.args[-1]!='Y': os.system('pythonw myprog.py Y') # or whatever your program's name is` `# Your program's code` – Anonymous Jun 05 '18 at 20:21
  • @Anonymous You sometimes need to have a finer control over whether the console is shown or not. When I freeze a program with Pyinstaller, I want the console to be there so that I can read errors if the packaging didn't work, and hide the console if everything goes well. – Guimoute May 06 '21 at 11:01
5

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.

1

just change the file extension from .py to .pyw

0

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.

SiL3NC3
  • 690
  • 6
  • 29
-1

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()
mo-han
  • 397
  • 5
  • 5