I have written a nice python script that parses XML and adds some sophisticated logic to then interface with an external command via subprocess module.
Most of the subprocess.Popen calls do exactly what they're supposed to, but the last one simply refuses to execute. No error message , it just doesn't do what it's supposed to. I even put the actual CMD into a shell script surrounded by debugging statements, and the shell script gets executed, but not the actual CMD.
More infuriatingly, the very same line of code in a separate .py file executes just fine.
I have no idea why or how this could be?
The python code is generating a file and tries to invoke the external command with options
p = subprocess.Popen([CMD,'object','new_host','--file','/tmp/add.1234'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
r = p.communicate()
print r
this logic works in the standalone file, but not in the larger python script (which has other working Popen calls in it).
Does anybody have an idea why this could be?
PS: I can not update python to a more recent version
Related
I am a newbie to python and would like to seek some advice. I having a script now where the function of this script can only be executed after I run a command i.e. python run trial.py. However, I would like to automate this process by using a subprocess function in a new python file called 'run.py' to run the trial.py script.
After that, I would wish to convert run.py file into an exe file to ease the execution for other users.
I have tried to perform the below steps.
1. saved the scripts (trial.py & run.py) in same directory.
2. Execute both of the files in same conda virtual environment.
3. Successfully execute run.py by using ```subprocess.run('xxx run trial.py')```
4. Converted the run.py into an exe file
5. Tried to execute the exe file and it is running, but **failed** to show the output that suppose to be appeared after running trial.py.
Would like to seek advice is any steps on above did wrongly or need to be improvised? I need to deal with confidential data hence the easiest way I can do is by using pyinstaller to allow another user to execute.
Hope to hear some advice
UPDATE
I had tried to use the codes below,
import subprocess
import sys
from subprocess import PIPE, STDOUT
command ='python run trial.py'
run = subprocess.Popen(command, shell=True, stdin=PIPE, stdout=PIPE, stderr=STDOUT)
Now the exe file is able to be generated and able to run, but it doesn't appear the expected output. It ended without any error message. It works well when I run the script in python..
Wish to hear advice from all of you..
With subprocess, you can try it:
command = 'Your command' # Example: command = 'python trial.py'
process = subprocess.Popen(command, shell=True, stdout=sys.stdout, stderr=sys.stderr)
I would wish ... to ease the execution for other users.
As I've understood your case, using subprocess and making an exe file out of your python file (which is not an easy task) is not a good fit for you.
Instead, I recommend you to have a look at make files as they are well-known for simplifying your commands.
for example you can have a make file like this:
run:
python trial.py
And users can simply run make run, and python trial.py will run instead.
The possibilities are endless.
You can also make a bash file that is an executable,
# !/bin/bash
python trial.py
And it will simply run like exe files.
I'm learning to use the subprocess module.
I'm trying to run a .bat script under subprocess. The .bat script writes to a file every time it's called by double-clicking, but won't write to the same file when called from subprocess.
It's similar to this question, but in my case I'd much rather adapt the caller python script then the callee .bat script. The .bat is what I'm about to test.
My code follows. Path and name altered for brevity.
import subprocess
p=subprocess.Popen(r"path\foo.bat", shell=True, stdin = subprocess.PIPE, stdout = subprocess.PIPE)
p.communicate(input='\r\n')
I will need to fill in user input as the .bat runs, so (I think) I need to call Popen directly rather than using convenience functions. But other than that direct call I think the issue is not related, because the file writing should occur before the .bat's first need for user input.
Ommitting the communicate call or each of the arguments to Popen were tried and failed.
How can I change my python script to give the .bat file-writing privileges?
The obvious security implications are not relevant to my use case, the .bat is trusted.
EDIT: when implementing Rptk99's suggestion I've noticed that I can replace the path to the .bat with any string (literally, I've tried "hjklhjilhjkl"), and I'll get the same behaviour: the python prompt becomes interactive again. So I have a more fundamental problem: I cannot see any errors returned from the call.
I have a python app that has lots of outputs on the screen which can be used for debugging. out of all the logging techniques, "script" command works well for me because I can see the output on the screen as well as logging it. I want to include that at the beginning of my python app to run automatically and log everything, when I do, however, the python program doesn't run. as soon as I type exit at the terminal (which stops script logging) the app starts working. The command I'm using is:
command="script /tmp/appdebug/debug.txt"
os.system(command)
I have also tried script -q but the same issue is there. Would appreciate any help.
Cheers
Well, I did find the answer for anyone who is interested:
https://stackoverflow.com/questions/15507602/logging-all-bash-in-and-out-with-script-command
and
Bash script: Using "script" command from a bash script for logging a session
I will keep this question as others might have the same issue and finding those answers wasn't exactly easy :)
Cheers
Try to use subprocess, like so:
from subprocess import Popen, PIPE
p = Popen(['script', '/tmp/appdebug/debug.txt'], stderr=PIPE, stdout=PIPE)
stdout, stderr = p.communicate()
script is a wrapper for a session of interactions. Even if it appears to terminate quickly after being started in a shell, this is not so; instead it starts a new shell in which you can interact so that everything is logged to a file.
What does this mean for you?
Your approach of using script cannot work. You start script using os.system which will wait for script to terminate before the next Python statement is executed. script's work will only happen before it terminates (i. e. during the uninteresting waiting period of your Python program).
I propose to use script -c yourprog.py yourprog.log instead. This will execute and wrap the yourprog.py and the session will be stored in yourprog.log.
I may not at all understand this correctly, but I am trying to allow a Python program to interface with a subprocess that runs commands as if on a Linux shell.
For example, I want to be able to run "cd /" and then "pwd later in the program and get "/".
I am currently trying to use subprocess.Popen and the communicate() method to send and receive data. The first command, sent with the Popen constructor, runs fine and gives proper output. But I cannot send another command via communicate(input="pwd").
My code so far:
from subprocess i
term=Popen("pwd", stdout=PIPE, stdin=PIPE)
print(flush(term.communicate()))
term.communicate(input="cd /")
print(flush(term.communicate(input="pwd")))
Is there a better way to do this? Thanks.
Also, I am running Python 3.
First of all, you need to understand that running a shell command and running a program aren't the same thing.
Let me give you an example:
>>> import subprocess
>>> subprocess.call(['/bin/echo', '$HOME'])
$HOME
0
>>> subprocess.call(['/bin/echo $HOME'], shell=True)
/home/kkinder
0
Notice that without the shell=True parameter, the text of $HOME is not expanded. That's because the /bin/echo program doesn't parse $HOME, Bash does. What's really happening in the second call is something analogous to this:
>>> subprocess.call(['/bin/bash', '-c', '/bin/echo $HOME'])
/home/kkinder
0
Using the shell=True parameter basically says to the subprocess module, go interpret this text using a shell.
So, you could add shell=True, but then the problem is that once the command finishes, its state is lost. Each application in the stack has its own working directory. So what the directory is will be something like this:
bash - /foo/bar
python - /foo
bash via subprocess - /
After your command executes, the python process's path stays the same and the subprocess's path is discarded once the shell finishes your command.
Basically, what you're asking for isn't practical. What you would need to do is, open a pipe to Bash, interactively feed it commands your user types, then read the output in a non-blocking way. That's going to involve a complicated pipe, threads, etc. Are you sure there's not a better way?
I'm having trouble using mutilple subprocess calls back to back.
These 2 work fine:
subprocess.call(["gmake", "boot-tilera"], cwd="/home/ecorbett/trn_fp")
p = subprocess.Popen(["gmake", "run-tilera"], stdout=subprocess.PIPE, cwd="/home/ecorbett/trn_fp")
However, I get an error when I try to run this call directly after:
time.sleep(10)
subprocess.call(["./go2.sh"], cwd="/home/ecorbett/trn_fp/kem_ut")
I added sleep in there because I need a few seconds before I run the "./go2.sh" program. Not sure if that is the issue.
Any advice?
A possible reason why your shell script is working on the command-line is that the shebang line was not written correctly (or not written at all). See an example in which the script would work from a command line but not as a Python subprocess: Is this the right way to run a shell script inside Python?
If your shell script did not have a shebang line specified, it would work from command line because $SHELL is set in your environment and the script is taking that as a default. When running from a python subprocess, python does not know what it is and fails with OSError: [Errno 8] Exec format error. The subprocess.call() to gmake worked because it is a binary program and not a shell script. Using the argument shell=True gave an instruction to interpret the argument exactly as it would in a shell.
However, be careful about using shell=True in subprocess.call() as it may be insecure in some cases: subprocess Python docs.