I've console application on Python. I try to use xdg-open and run it in background, but I can't. I tried
os.system('xdg-open http://google.com &')
subprocess.call('xdg-open http://google.com &', shell=True)
I don't know what you mean by
but I can't
because it works for me. I imagine, however, that you're complaining that the parent process does not close until the child has.
That code is, however, an outdated practice (if it ever was in favour); the modern equivalent would be
process = subprocess.Popen(['xdg-open', 'Dunno.png'])
Instead of asking the shell to fork for you, this runs in the background from the start without ever passing through a shell. This should deal with the problem above, too.
If you want to capture sys.stdout, you can use
process = subprocess.Popen(['xdg-open', 'Dunno.png'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
which redirects the output of the process' stdout and stderr to buffers. (You can access those buffers with process.stdout and process.stderr and communicate either by reading and writing to those or using process.communicate.
You can get the return code with process.returncode.
If your problem is not this, a problem description (traceback?) would be useful. It's also worth checking that the behaviour of using xdg-open in the shell is what you expect.
Related
I am creating a subprocess using this line of code:
p = subprocess.Popen(["doesItemExist.exe", id], shell=False)
and when I run the script while I have the Task Manager open, I can see that it creates two processes and not one. The issue is that when I go to kill it, it kills one (using p.kill()), but not the other. I've tried looking online but the only examples I find are about shell=True and their solutions don't work for me. I've confirmed that that line only gets called once.
What can I do? Popen is only giving me back the one pid so I don't understand how to get the other so I can kill both.
I ended up being able to deal with this issue by creating a clean up function which just uses the following:
subprocess.run(["taskkill", "/IM", "doesItemExist.exe", "/F"], shell=True)
This will kill any leftover tasks. If anyone uses this, be careful that your exe has a unique name to prevent you from killing anything you don't mean to. If you want to hide the output/errors, just set the stdout and stderr to subprocess.PIPE.
Also, if there is no process to kill it will report that as an error.
Summary
I am automating xfoil with the subprocess module. I would like to be able to start an xfoil session with several commands and leave it open for the user to take on.
This would help debugging and also more generally to have a basic routine to start xfoil (without manually typing the same set of commands every time).
I am able to run any xfoil command using subprocess.communicate().
However, when open with subprocess xfoil systematically closes without user action.
Example
With the following code, you can see xfoil opening and closing quickly.
import subprocess
XFOIL_PATH = 'xfoil.exe'
xfoil = subprocess.Popen(XFOIL_PATH, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True)
actions = 'NACA 0012\nGDES\n'
xfoil.communicate(input=actions)
Note
I've used subprocess.Popen() with Rhino and Rhino stays open until I close it manually. I do not understand why the behavior is different with xfoil.
I suspect it has something to do with the specific application's stdout but it's a wild guess. Hopefully it is possible to do something about it.
My understanding is when you call communicate() with the input parameter, the call will close stdin, which terminates the xfoil.exe process. Try the following instead of calling communicate():
xfoil.stdin.write(actions)
xfoil.stdin.flush()
After that, the process continues until you exit your script.
Update
If you want the xfoil project to continue even after your script ends, please look into pexpect.
Piping cmd.exe with a subprocess in order of embedding a console works fine in most cases. When using a stdout.read(1)-thread of course. However this thread is getting nothing for few commands (i spotted this for python itself as well as for python programms).
I know there are lots of questions about output from children, but this is about loosing a child's child's (and so on) output. The output of cmd.exe itself as well as most of commands is easily tracked out. Also I can assume that the same occurs for input as the interactive python shell within cmd.exe is not closing when exit() is entered.
This could be a buffering issue - but that would be strange as buffering is disabled for Popen (and p.stdin.flush() is used as python won't start within p elseways). Also this could be caused because of bad inheritance of the processes and their standard i/o streams, but i actually hope it's not.
I can see there could be good use for example code but this is actually as I mentioned embedded. So if someone sees a theoretical problem I can skip the process of exporting that code :) However I should add an example even tough this board gives lots of examples relating to cmd.exe and popen. It would take less time than I spent already on googling for the solution.
The basic problem is
subprocess.Popen("cmd.exe", stdin = -1, stdout = -1, stderr = -2, bufsize=0)
that not all children of that subprocess seem to be using the pipes. The cmd starts accepting further commands as soon as it's child has been killed (what's probably ensuring the loss of it's output).
I am using below code for running unix commands:
cmd = 'ls -l'
(status,output) = commands.getstatusoutput(cmd)
print output
But the problem is that it shows output only after the command completed, but i want to see the output printed as the execution progresses.
ls -l is just dummy command, i am using some complex command in actual program.
Thanks!!
Since this is homework, here's what to do instead of the full solution:
Use the subprocess.Popen class to call the executable. Note that the constructor takes a named stdout argument, and take a look at subprocess.PIPE.
Read from the Popen object's STDOUT pipe in a separate thread to avoid dead locks. See the threading module.
Wait until the subprocess has finished (see Popen.wait).
Wait until the thread has finished processing the output (see Thread.join). Note that this may very well happen after the subprocess has finished.
If you need more help please describe your precise problem.
Unless there are simpler ways in Python which I'm not aware of, I believe you'll have to dig into the slightly more complex os.fork and os.pipe functions.
Basically, the idea is to fork your process, have the child execute your command, while having its standard output redirected to a pipe which will be read by the parent. You'll easily find examples of this kind of pattern.
Most programs will use block buffered output if they are not connected to a tty, so you need to run the program connected to a pty; the easiest way is to use pexpect:
for line in pexpect.spawn('command arg1 arg2'):
print line
I know this has been asked a lot of times but I've yet to find a proper way of doing this. If I want to run a local command the docs say I have to use subprocess as it's replacing all other methods such as os.system/peopen etc.
If I call subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) in my program and the command is for example a openvpn directive which connects my computer to a VPN the process will hang indefinitely since openvpn returns it's output ending with a new line but hangs in there while connected and so does my program (frozen).
Some say I should remove the stdout=subprocess.PIPE which indeed works in a non-blocking way but then everything gets printed to the console instead of me having some sort of control over the output (maybe I dont want to print it).
So is there some sort of proper way of doing this, an example maybe of executing commands in a non-blocking way and also having control over the output.?
If you specify stdout=PIPE, then your subprocess will write to the pipe and hang when the pipe buffer is full. The python program shoudn't hang - Popen is asynchronous which is why Popen.wait() can be called later to wait for the subprocess to exit. Read from Popen.stdout in order to keep the subprocess happy, and print, discard, or process the output as you see fit.
Consider running your process within a terminal. For example,
subprocess.Popen("xterm -e /bin/bash -c '/path/to/openvpn'", shell=True)
or even, you could try,
import shlex
subprocess.Poen(shlex.split("xterm -e /bin/bash -c '/path/to/openvpn'"), shell=False)