Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Prevent creating new console on Windows #346

Merged
merged 1 commit into from
Apr 12, 2018
Merged

Conversation

nanoant
Copy link

@nanoant nanoant commented Jan 30, 2018

When running Jupyter via pythonw e.g. pythonw -m qtconsole, jupyter_client launches new kernel via python.exe which is a console application on Windows - a side-effect of that is a new empty console window created and shown as long as kernel is running.

This patch adds CREATE_NO_WINDOW 0x08000000 to Windows specific creationflags. This flag is not exported by subprocess module therefore has to be provides numerically.

Read more, e.g.:
https://stackoverflow.com/questions/2935704/running-shell-commands-without-a-shell-window

@takluyver
Copy link
Member

Thanks! I've got a couple of concerns about doing this:

  1. If you're running the Jupyter application from a console window, does passing CREATE_NO_WINDOW mean the kernel process can't print logging to the console? That logging can be pretty useful in some situations.
  2. We've had some issues with pythonw where a process trying to write to stdout/stderr fills up a buffer that nothing is reading from, and then hangs. We have some code to detect pythonw and specifically work around this. Is using python with CREATE_NO_WINDOW going to lead to the same issue because nothing is reading stdout/stderr?

@nanoant
Copy link
Author

nanoant commented Feb 13, 2018

@takluyver No, this flags just prevents creating console window if the parent process is GUI app (has no own console handle), but the stdin/out functionality should not be affected.

Just to make sure, I have created simple proof-of-concept script that shows that CREATE_NO_WINDOW does no break Popen:

def test():
    import subprocess
    with subprocess.Popen(['cmd', '/c', 'dir'],
                          creationflags=0x08000000,  # CREATE_NO_WINDOW
                          stdout=subprocess.PIPE,
                          stderr=subprocess.PIPE,
                          shell=False) as p:
        out = p.stdout.read()
    return out.decode('utf-8')

if __name__ == '__main__':
    import ctypes
    MessageBox = ctypes.windll.user32.MessageBoxW
    MessageBox(None, test(), 'cmd', 0)

Now when I run it via pythonw (no console - GUI app) there's no extra console window, but if I comment out creationflags line and run pythonw there's cmd popup shown for a fraction of second.

In case when the script is run via python then it does not matter since the python is console app, just before MessageBox is shown.

P.S. This all is caused by Windows weird separation for console vs GUI apps, that simply does not exist in UNIX world, and I wouldn't care, but I recently have to work on Windows workstation :).

@nanoant
Copy link
Author

nanoant commented Apr 12, 2018

@takluyver Hello, Is there anything else I can do to get this checked in?

@takluyver takluyver added this to the 5.3 milestone Apr 12, 2018
@takluyver
Copy link
Member

Oh sorry, it had just dropped off my radar.

Can you confirm that if you use this option from a process running in a console, without piping stdout/stderr, the child process can still write to the console that it's in?

If this causes problems for Windows users when we release it, I might ping you to ask about it.

@nanoant
Copy link
Author

nanoant commented Apr 12, 2018

Can you confirm that if you use this option from a process running in a console, without piping stdout/stderr, the child process can still write to the console that it's in?

Yes, the proof is my post above: #346 (comment)

@takluyver
Copy link
Member

Sorry, that's not quite what I meant - I'm asking you to do it without stdout=subprocess.PIPE, stderr=subprocess.PIPE, and check that the child process can write directly to the console.

@nanoant
Copy link
Author

nanoant commented Apr 12, 2018

@takluyver Yes I now get your point, let me rework the patch so it takes this countermeasure only for pythonw which is already checked at the top of the function.

When running Jupyter via pythonw e.g. pythonw -m qtconsole, jupyter_client launches new kernel via python.exe which is a console application on Windows - a side-effect of that is a new empty console window created and shown as long as kernel is running.

This patch adds CREATE_NO_WINDOW 0x08000000 to Windows specific creationflags. This flag is not exported by subprocess module therefore has to be provides numerically.
@takluyver
Copy link
Member

Thanks, that looks good to me now. :-)

@takluyver takluyver merged commit b754994 into jupyter:master Apr 12, 2018
takluyver added a commit that referenced this pull request Apr 12, 2018
@nanoant
Copy link
Author

nanoant commented Apr 12, 2018

@takluyver Thanks a lot! Cheers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants