3

I want to spawn a subprocess, and it would be good if everything would happen in the background without opening a new Windows console.

First I thought that something is wrong with my code, because it lead to errors while sending input to the subprocess. A Command like String e.g. generated an error

Unknown Action: tring

Meaning, from time to time the first character of the input sent to the subprocess via stdin.write was missing.

That is the code:

    self.sp = subprocess.Popen(
        args,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE
    )

Now I've tried the following, and everything works fine. The problem is the newly opened consoled.

    self.sp = subprocess.Popen(
        args,
        stdin=subprocess.PIPE,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        creationflags = subprocess.CREATE_NEW_CONSOLE
    )

Is there another way to achieve this without opening a new Windows console?

 


Your links lead me to this description of the CREATE_NEW_WINDOW flag

A process can also create a console by specifying the CREATE_NEW_CONSOLE flag in a call to CreateProcess. This method creates a new console that is accessible to the child process but not to the parent process. Separate consoles enable both parent and child processes to interact with the user without conflict. If this flag is not specified when a console process is created, both processes are attached to the same console, and there is no guarantee that the correct process will receive the input intended for it. Applications can prevent confusion by creating child processes that do not inherit handles of the input buffer, or by enabling only one child process at a time to inherit an input buffer handle while preventing the parent process from reading console input until the child has finished.

If one could just create a new console without opening a window.


This seems to have solved the problem

bufsize=1

Thank you.

martinenzinger
  • 2,166
  • 2
  • 17
  • 20
  • 1
    You can try this method https://stackoverflow.com/a/7006424/6120211 – Seer.The Jul 14 '17 at 13:38
  • There's no obvious reason that remaining attached to the parent console should be a problem. Can you provide a minimal example? – Eryk Sun Jul 15 '17 at 00:46
  • 1
    Anyway, try the [creation flag](https://msdn.microsoft.com/en-us/library/ms684863) `CREATE_NO_WINDOW`, which implicitly creates a new console (instance of conhost.exe) that doesn't have a window. – Eryk Sun Jul 15 '17 at 00:49
  • It is also possible that the problem may be in the child process. – Harry Johnston Jul 15 '17 at 05:07
  • Thank you. I've tried it with `CREATE_NO_WINDOW` and I got the same error. I've also tried adding `CREATE_NO_WINDOW` and `CREATE_NEW_CONSOLE` up to `0x08000010`. This just opens the window again. – martinenzinger Jul 15 '17 at 06:33
  • @HarryJohnston I've downloaded a precompiled version for the child process part. What is a little strange though is that the parent process already runs in the background. Maybe it has something to do that? – martinenzinger Jul 15 '17 at 12:55
  • 1
    That is certainly relevant information which should be included in the question, but it doesn't explain the symptoms. Assuming the problem is caused by a bug in the child, one possible workaround would be to explicitly create a console (in the parent) and then hide it, using AllocConsole(), GetConsoleWindow() and ShowWindow() - you can call most Win32 API functions in Python so you should be able to do that - but it isn't ideal, since the console will still flash up briefly. – Harry Johnston Jul 15 '17 at 14:53
  • @HarryJohnston, if the OP is using python.exe, then the parent process already has a console, unless it was run detached. The OP wants a new console without a window, which is what `CREATE_NO_WINDOW` does. But apparently there's a bug in the child process that's being worked around by creating a new console *with* a window. – Eryk Sun Jul 16 '17 at 19:55
  • The quoted paragraph about sharing console input should be irrelevant. Data written to a pipe is being lost, not data written to a console. Your Python process has the write end, and the child process has the read end as its `StandardInput` handle. – Eryk Sun Jul 16 '17 at 20:00
  • @eryksun, the OP says the the parent process is running in the background, I assume that means they are using `pythonw.exe`. – Harry Johnston Jul 16 '17 at 21:13
  • 1
    @HarryJohnston, the task manager displays processes that don't have a window as "background" processes. That applies to python.exe when run via another console app such as cmd.exe. The console window is hosted by conhost.exe, but it stores the process and thread IDs of the effective owner as window data (index 0 and 4), which, for example, is used by `GetWindowThreadProcessId`. When the current owner exits, the console promotes the next attached process in its list as the owner, until none are left and the console exits. – Eryk Sun Jul 16 '17 at 21:32
  • 1
    @eryksun, good point. I hadn't noticed that had changed in Windows 10. toas939, can you clarify how you are launching the parent process? – Harry Johnston Jul 16 '17 at 21:42
  • It starts with a node.js app that **[spawns](https://nodejs.org/api/child_process.html#child_process_child_process_spawn_command_args_options)** modules built with python. That works great for 7 other modules and the first part seems to work for the module in question as well. The node.js app provides the UI and the rest is running in the background. The python modules depend on certain python packages and this one pip package is a wrapper for a windows console app. In the package **subprocess.Popen** is used to write and read messages to/from the console app. – martinenzinger Jul 17 '17 at 06:24
  • 1
    Please update your question with the `spawn` call that's executing python[w].exe or whatever frozen Python executable is calling `subprocess.Popen`. It's not clear to me how these pieces of your problem fit together. – Eryk Sun Jul 17 '17 at 15:12
  • 1
    `bufsize=1` is setting line buffering for the `Popen` object's `stdin`, `stdout`, and `stderr` files. However, that has no effect unless text mode is used (e.g. `universal_newlines=True`). Otherwise in binary mode it will still use the default 8 KiB buffer size. Anyway, if you are using text mode, and flushing line-by-line to the pipe helps, then it definitely seems like you're working around a bug in how the child reads from its `StandardInput`. – Eryk Sun Jul 17 '17 at 19:32

1 Answers1

3

"Is there another way to achieve this without opening a new Windows console?" Yes there is ! You can use the creation flag CREATE_NO_WINDOW, like this:

creationflags=subprocess.CREATE_NO_WINDOW

And voilà ! No windows !

Glycerine
  • 7,157
  • 4
  • 39
  • 65
Medsiv
  • 270
  • 3
  • 12