Problem when invoking command prompt from a python script - python

I would like some help towards invoking a command prompt (& passing some argument to the command prompt) from a python script.
I use pyqt4 for developing the UI and on the UI I have a run button. On selection of run button, I would like to invoke a command prompt and pass on some script name as the argument.
self.connect(run_button, SIGNAL('clicked()'), self.runscript) # this is my run button signal and i'm calling the runscript()
def runscript(self):
print 'Inside Run Script'
os.chdir('C:\PerfLocal_PAL')
try:
subprocess.call(['C:\windows\system32\cmd.exe'])
except:
print 'Exception Caused.'
When I click on run button, the application dies and it does not invoke the command prompt at all. I tried with os.system as well same result.
also, I would like to know how to pass the argument to the call function?
Any help towards this is highly appreciated.
Thanks,

To correctly define file paths in Python on Windows, you need to do one of three things:
Use forward slashes: "C:/PerfLocal_PAL" (Python understands forward slashes regardless of platform)
Use raw strings: r"C:\PerfLocal_PAL"
Escape the backslashes: "C:\\PerfLocal_PAL"
This affects both your chdir call and your subprocess.call invocation.
However, you will also have trouble due to the fact that your parent process is a GUI application, and hence has no console streams for stdin, stdout and stderr. Try using the following instead to get a completely separate command window:
subprocess.call("start", shell=True)
You may also want to use the "/D" argument of start to set your working directory, rather than changing the cwd of the parent process:
subprocess.call(["start", "/DC:\\PerfLocal_PAL"], shell=True)

Have you tried debugging this at all? Which line does the script fail on? Does it actually start the runscript function at all?
Regarding passing arguments to cmd.exe, have a look at the documentation for subprocess.call. It will show you that you can have a second argument providing the command line parameters to the program, e.g.
subprocess.call(["C:\windows\system32\cmd.exe", "scriptname.bat"])

One problem is that subprocess.call will block until it is complete, and cmd.exe will not return until you exit it. That answers the 'just dies' but may not explain the console never appearing. Start with this:
subprocess.Popen(['C:\Windows\system32\cmd.exe'])
That at least will not block. If you can get it to appear, try your arguments, like this:
subprocess.Popen(['C:\Windows\system32\cmd.exe', 'program_or_script', 'arg1'])

Your signal connection and your subprocess call seems to be fine.
Change your chdir call to:
os.chdir(r'C:\PerfLocal_PAL')
I guess the error you are getting is of the form (when you launch your application from the command prompt):
WindowsError: [Error 123] The filename, directory name, or volume label syntax is incorrect: 'C:\PerfLocal_PAL'

Related

Running batch file with subprocess.call does not work and freezes IPython console

This is a frequent question, but reading the other threads did not solve the problem for me.
I provide the full paths to make sure I have not made any path formulation errors.
import subprocess
# create batch script
myBat = open(r'.\Test.bat','w+') # create file with writing access
myBat.write('''echo hello
pause''') # write commands to file
myBat.close()
Now I tried running it via three different ways, found them all here on SO. In each case, my IDE Spyder goes into busy mode and the console freezes. No terminal window pops up or anything, nothing happens.
subprocess.call([r'C:\\Users\\felix\\folders\\Batch_Script\\Test.bat'], shell=True)
subprocess.Popen([r'C:\\Users\\felix\\folders\\Batch_Script\Test.bat'], creationflags=subprocess.CREATE_NEW_CONSOLE)
p = subprocess.Popen("Test.bat", cwd=r"C:\\Users\\felix\\folders\\Batch_Script\\")
stdout, stderr = p.communicate()
Each were run with and without the shell=True setting, also with and without raw strings, single backslashes and so on. Can you spot why this wont work?
Spyder doesn't always handle standard streams correctly so it doesn't surprise me that you see no output when using subprocess.call because it normally runs in the same console. It also makes sense why it does work for you when executed in an external cmd prompt.
Here is what you should use if you want to keep using the spyder terminal, but call up a new window for your bat script
subprocess.call(["start", "test.bat"], shell=True)
start Starts a separate Command Prompt window to run a specified program or command. You need shell=True because it's a cmd built-in not a program itself. You can then just pass it your bat file as normal.
You should use with open()...
with open(r'.\Test.bat','w+') as myBat:
myBat.write('echo hello\npause') # write commands to file
I tested this line outside of ide (by running in cmd) and it will open a new cmd window
subprocess.Popen([r'Test.bat'], creationflags=subprocess.CREATE_NEW_CONSOLE)
Hey I have solution of your problem :)
don't use subprocess instead use os
Example :
import os
myBatchFile = f"{start /max} + yourFile.bat"
os.system(myBatchFile)
# "start /max" will run your batch file in new window in fullscreen mode
Thank me later if it helped :)

Why Does Python Call a Subprocess Command Incorrectly?

This is a follow up on a previous question as I have made progress(which is irrelevant at this point). It is worth noting that I am learning python and barely know what I am doing, however, I am familiar with programming. I am trying to call an SCP command in the windows terminal through python. However, it is not doing the desired effect. The script runs smoothly with no errors and it prints the debug commands as I have written them. However, the SCP call does not actually go through on the other end. To make sure I have the right command, I have it set to print the same command that it called afterwards. When I copy this printed command and paste it into the windows command terminal, it gives the desired effect. Why is the same command not working correctly in python? Thanks. This is my script:
import subprocess
subprocess.run(['scp', 'c:/users/<name>/desktop/OOGA.txt', 'pi#<IP>:here/'], shell=True)
print ("done")
print ('scp', 'c:/users/<name>/desktop/OOGA.txt', 'pi#<IP>:here/')
Try using raw string if shell is set to True:
from subprocess import run as subrun
status = subrun(r'scp c:/users/<name>/desktop/OOGA.txt pi#<IP>:here/',shell=True)
print("Done")
print(status)

Calling a python script from another python script with arguments does not work

I am well aware that there are multiple threads dealing with this problem because I used them in an attempt to self-teach me how to do it. However, for me it does not work and I wondered if someone could help me find my error.
So I got one program (let's call it prog1) that calls a script for every string-variable like this:
os.system(r'C:\Users\user\docs\bla\script.py %s'%variable)
In script.py I now just wanted to test if this call worked by disabling all code but just doing:
def main(string):
print(string)
root
if __name__ == "__main__":
print('I got executed')
main(sys.argv[1])
The Problem is, if I execute prog1 nothing happens. No errer - so it runs through and the console pops up for a Brief second. However, nothing happens - no string is printed. If I execute script.py directly it works though.
EDIT: I got it to execute without error with the subprocess package by using:
subprocess.call(r'C:\...\script.py' %s' %variable,shell = True)
However, the problem stays the same - nothing happens. Or well, I noticed now that in the Background a Windows window pops up asking me with which program I want to execute files with the ending '.py' but this is not helping me, because I want to execute in console :(
Try using the subprocess module, it allows for more flexible parametres and other configuration changes :
import subprocess
subprocess.check_call(["python.exe", r"C:\Users\user\docs\bla\script.py", variable])
And when executed :
subprocess.check_call(["python", r"C:\Users\user\docs\bla\script.py", "Blue"])
I got executed
Blue
More information about the subprocess : https://docs.python.org/2/library/subprocess.html

Python on Notepad++ : How to pass command line arguments?

"ValueError: need more than 1 value to unpack - Learn Python the Hard Way Ex: 13"
This problem has been discussed a lot of times on this forum. Is there a way to pass on the arguments in the Notepad++ editor itself?
Writing the code in the Notepad++ editor and then executing it on python's default environment after providing the arguments should make this work - but can we directly pass the arguments from notepad++?
P.S - Just started with python - no prior knowledge.
Passing command line arguments can only be done on the command line itself.
Or you can call it via another Python program using os.system to execute command line arguments.
os.system : Execute the command (a string) in a subshell. This is implemented by calling the Standard C function system(), and has the same limitations
import os
os.system("Program_Name.py Variable_Number_Of_Arguements"
You could also use call from subprocess:
from subprocess import call
call(["Program.py", "Arg1", "Arg2"])
Yes, it is possible.
After writing code in Nodepad++, click File > Open Containing Folder > cmd.
This will open up a cmd window where you can type a query like below:
python filename.py arguments

Python subprocess module with pre-populated environment

Question can be related to Use python subprocess module like a command line simulator
I have written some infrastructure code called my_shell to which you can pass shell commands of my application that looks like this
class ApplicationTestShell(object):
def __init__(self):
'''
Constructor
'''
self.play_ground_dir = "/var/tmp/MyAppDir"
ensure_dir_exists_and_empty(self.play_ground_dir)
def execute_command(self, command, on_success = None, on_failure = None):
p = create_shell_process(self, self.play_ground_dir)
sout, serr = p.communicate(input = command)
if p.returncode == 0:
on_success(sout)
else:
on_failure(serr)
def create_shell_process(self, cwd):
return Popen("/bin/bash", env= {WHAT DO I DO HERE?},cwd = test_dir, stdout=PIPE, stderr=PIPE, stdin=PIPE)
The interesting bit to me here is the env parameter. Python expects like a 'map' datastructure of all environment variable. My application requires several variables exported and set. The script for setting and exporting is generated by running say '/bin/appload myapp' (Assume appload is always available on the path). What I do currently
is when I call p.communicate I do the following
p.communicate(input = "eval `/bin/appload myapp`;" + command)
So basically before running the command I call the infrastructure setup.
Is there any way to do this in a better fashion in Python. I somehow want to push the eval /bin/appload part to the env parameter on the Popen class OR as part of the shell creation process.
What are the problems with my current implementation? (I feel it is hacky but I may be wrong)
It depends on how /bin/appload myapp works. If it only guarantees that it will output bash syntax, then parsing that output in Python in order to construct the environment object there is almost certainly more trouble than it's worth (you might need to support parameter and variable expansion, subshells, process substitution, etc, etc). On the other hand, if you are sure that /bin/appload myapp will only ever output lines of the form "VARIABLENAME=someword", then that's pretty trivial to parse in Python and you could move it into your Python code if you like.
There are an awful lot of different directions you could go with these requirements; you could capture the output of appload myapp into a tempfile and set the subprocess's $BASH_ENV to that filename; that would cause the shell to source your environment setup before running your command in a way that some might consider cleaner. You could give your command (with the eval-ing prefix) as the first argument to Popen and pass shell=True, and let Popen do the bash invocation on its own (setting $SHELL explicitly to bash if necessary). You could use bash's -c option to specify the code to run on the command line rather than via stdin. You could have a multi-tiered approach by invoking a shell from Python which eval's the appload myapp environment and then exec's another shell underneath it, so that the first doesn't show up in ps listings and the command given to create_shell_process has the shell all to itself (although that shouldn't really matter). You could do a lot of things, depending on what your concerns are with respect to how the shell is invoked, how it looks in ps listings, whether you want your command to still be run if the appload myapp output produces an error when eval'd, etc. But for a general solution, I think what you have is perfectly fine.
I don't see any real problems with the implementation, besides cosmetic things or minor things that probably only came from copying and pasting the code: create_shell_process doesn't use its cwd parameter, and the on_success and on_failure parameters look like they're optional but the defaults will break things (you can't call None).

Categories