Running a command-line command in terminal using python - python

I have to basically run a terminal-command using python script. General way of doing this would be
In [1]: import subprocess
In [2]: subprocess.Popen(['python some-python-script.py'],shell=True)
Out[2]: <subprocess.Popen at 0x103425358>
Now, my requirement is that this script will be triggered n (<=10) times printing some output. How do i ensure that everytime its triggered using python, it opens in new terminal tab printing the output?
Checked couple of refernce online and tried using
In [11]: os.system("Terminal -x python some-python-script.py")
sh: Terminal: command not found
but doesn't help.
I am on OSx Sierra but a platform independent solution is welcome!!

You can use check_output from the subprocess module. As your command must be executed more than once, you can just call the function inside for loop. The script may look something like this (the upper bound of the range may be variable):
import subprocess
for idx in range(5):
print(subprocess.check_output(['python3', 'full-path-to-script.py'], encoding='utf-8'))
As mentioned in the documentation, the check_output function returns the data as encoded bytes, but as the encoding is specified in my example, the output will be UTF-8 encoding string. Depending on your command the decoding to text may need to be handled separately.

Related

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)

Using subprocess in Python, I get different results when in Python cmd and Python IDLE

I hope the title makes sense. To give specifics:
I am using csvtotable (https://github.com/vividvilla/csvtotable) to generate HTML tables from CSVs. I have installed via pip and am able to run a command line command:
csvtotable test1743.csv test1743.html
to generate a HTML page. All good so far.
I wanted to do this from within a Python script I had already written so I heard that subprocess was the way to do this. I looked up how to do it and understood that it can be done using the following:
subprocess.run('csvtotable test1743.csv test1743.html',shell=True)
So I tested this via the command line first by doing
python
from the command line and then running
import subprocess
subprocess.run('csvtotable test1743.csv test1743.html',shell=True)
Success! It worked. Fantastic.
However, when I try to do this from IDLE, it just returns a 1. I have checked the directory thinking that maybe the csv was missing from there, but it still doesn't work.
Am I misunderstanding how subprocess works?
Solved by finding a way to call the function without subprocess. I think the issue may have related to default arguments not being set when it is executed through python and hence why below I have had to specify so many arguments.
Code:
from csvtotable import convert
content = convert.convert("C:\\Users\\admin\\Google Drive\\test1743.csv",delimiter=",",quotechar='"',display_length=-1,overwrite=False,serve=False,pagination=True,virtual_scroll=1000, no_header=False, export=True, export_options=["copy","csv","json","print"])
convert.save("C:\\Users\\admin\\Google Drive\\test1743.html",content)
Note that the argument names had to be changed where they had a - in the name. I just changed any instance e.g. display-length to display_length in convert.py

Fetch PowerShell script from GitHub and execute it

Running into issues executing a PowerShell script from within Python.
The Python itself is simple, but it seems to be passing in \n when invoked and errors out.
['powershell.exe -ExecutionPolicy Bypass -File', '$Username = "test";\n$Password = "password";\n$URL
This is the code in full:
import os
import subprocess
import urllib2
fetch = urllib2.urlopen('https://raw.githubusercontent.com/test')
script = fetch.read()
command = ['powershell.exe -ExecutionPolicy Bypass -File', script]
print command #<--- this is where I see the \n.
#\n does not appear when I simply 'print script'
So I have two questions:
How do I correctly store the script as a variable without writing to disk while avoiding \n?
What is the correct way to invoke PowerShell from within Python so that it would run the script stored in $script?
How do I correctly store the script as a variable without writing to disk while avoiding \n?
This question is essentially a duplicate of this one. With your example it would be okay to simply remove the newlines. A safer option would be to replace them with semicolons.
script = fetch.read().replace('\n', ';')
What is the correct way to invoke PowerShell from within Python so that it would run the script stored in $script?
Your command must be passed as an array. Also you cannot run a sequence of PowerShell statements via the -File parameter. Use -Command instead:
rc = subprocess.call(['powershell.exe', '-ExecutionPolicy', 'Bypass', '-Command', script])
I believe this is happening because you are opening up PowerShell and it is automatically formatting it a specific way.
You could possibly do a for loop that goes through the command output and print without a /n.

Python script writing results to text file

Today I managed to run my first Python script ever. I'm a newb, on Windows 7 machine.
When I run python.exe and enter following (Python is installed in C:/Python27)
import os
os.chdir('C:\\Pye\\')
from decoder import *
decode("12345")
I get the desired result in the python command prompt window so the code works fine. Then I tried to output those results to a text file, just so I don't have to copy-paste it all manually in the prompt window. After a bit of Googling (again, I'm kinda guessing what I'm doing here) I came up with this;
I wrote "a.py" script in the C:/Pye directory, and it looked like this;
from decoder import *
decode("12345")
And then I wrote a 01.py file that looked like this;
import subprocess
with open("result.txt", "w+") as output:
subprocess.call(["python", "c:/Pye/a.py"], stdout=output);
I see the result.txt gets created in the directory, but 0 bytes. Same happens if I already make an empty result.txt and execute the 01.py (I use Python Launcher).
Any ideas where am I screwing things up?
You didn't print anything in a.py. Change it to this:
from decoder import *
print(decode("12345"))
In the Python shell, it prints it automatically; but the Python shell is just a helper. In a file, you have to tell it explicitly.
When you run python and enter commands, it prints to standard out (the console by default) because you're using the shell. What is printed in the python shell is just a representation of what object is returned by that line of code. It's not actually equivalent to explicitly calling print.
When you run python with a file argument, it executes that script, line by line, without printing any variables to stdout unless you explicitly call "print()" or write directly to stdout.
Consider changing your script to use the print statement.:
print(decode("12345"))

Running an outside program (executable) in Python?

I just started working on Python, and I have been trying to run an outside executable from Python.
I have an executable for a program written in Fortran. Let’s say the name for the executable is flow.exe. And my executable is located in C:\Documents and Settings\flow_model. I tried both os.system and popen commands, but so far I couldn't make it work. The following code seems like it opens the command window, but it wouldn't execute the model.
# Import system modules
import sys, string, os, arcgisscripting
os.system("C:/Documents and Settings/flow_model/flow.exe")
How can I fix this?
If using Python 2.7 or higher (especially prior to Python 3.5) you can use the following:
import subprocess
subprocess.call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
Runs the command described by args. Waits for command to complete, then returns the returncode attribute.
subprocess.check_call(args, *, stdin=None, stdout=None, stderr=None, shell=False)
Runs command with arguments. Waits for command to complete. If the return code was zero then returns, otherwise raises CalledProcessError. The CalledProcessError object will have the return code in the returncode attribute
Example: subprocess.check_call([r"C:\pathToYourProgram\yourProgram.exe", "your", "arguments", "comma", "separated"])
In regular Python strings, the \U character combination signals a
extended Unicode code point escape.
Here is the link to the documentation: http://docs.python.org/3.2/library/subprocess.html
For Python 3.5+ you can now use run() in many cases: https://docs.python.org/3.5/library/subprocess.html#subprocess.run
Those whitespaces can really be a bother. Try os.chdir('C:/Documents\ and\ Settings/') followed by relative paths for os.system, subprocess methods, or whatever...
If best-effort attempts to bypass the whitespaces-in-path hurdle keep failing, then my next best suggestion is to avoid having blanks in your crucial paths. Couldn't you make a blanks-less directory, copy the crucial .exe file there, and try that? Are those havoc-wrecking space absolutely essential to your well-being...?
The simplest way is:
import os
os.startfile("C:\Documents and Settings\flow_model\flow.exe")
It works; I tried it.
I'd try inserting an 'r' in front of your path if I were you, to indicate that it's a raw string - and then you won't have to use forward slashes. For example:
os.system(r"C:\Documents and Settings\flow_model\flow.exe")
Your usage is correct. I bet that your external program, flow.exe, needs to be executed in its directory, because it accesses some external files stored there.
So you might try:
import sys, string, os, arcgisscripting
os.chdir('c:\\documents and settings\\flow_model')
os.system('"C:\\Documents and Settings\\flow_model\\flow.exe"')
(Beware of the double quotes inside the single quotes...)
Use subprocess, it is a smaller module so it runs the .exe quicker.
import subprocess
subprocess.Popen([r"U:\Year 8\kerbal space program\KSP.exe"])
By using os.system:
import os
os.system(r'"C:/Documents and Settings/flow_model/flow.exe"')
Try
import subprocess
subprocess.call(["C:/Documents and Settings/flow_model/flow.exe"])
If it were me, I'd put the EXE file in the root directory (C:) and see if it works like that. If so, it's probably the (already mentioned) spaces in the directory name. If not, it may be some environment variables.
Also, try to check you stderr (using an earlier answer by int3):
import subprocess
process = subprocess.Popen(["C:/Documents and Settings/flow_model/flow.exe"], \
stderr = subprocess.PIPE)
if process.stderr:
print process.stderr.readlines()
The code might not be entirely correct as I usually don't use Popen or Windows, but should give the idea. It might well be that the error message is on the error stream.
in python 2.6 use string enclosed inside quotation " and apostrophe ' marks. Also a change single / to double //.
Your working example will look like this:
import os
os.system("'C://Documents and Settings//flow_model//flow.exe'")
Also You can use any parameters if Your program ingest them.
os.system('C://"Program Files (x86)"//Maxima-gcl-5.37.3//gnuplot//bin//gnuplot -e "plot [-10:10] sin(x),atan(x),cos(atan(x)); pause mouse"')
finally You can use string variable, as an example is plotting using gnuplot directly from python:
this_program='C://"Program Files (x86)"//Maxima-gcl-5.37.3//gnuplot//bin//gnuplot'
this_par='-e "set polar; plot [-2*pi:2*pi] [-3:3] [-3:3] t*sin(t); pause -1"'
os.system(this_program+" "+this_par)
import os
path = "C:/Documents and Settings/flow_model/"
os.chdir(path)
os.system("flow.exe")
Note added by barlop
A commenter asked why this works. Here is why.
The OP's problem is os.system("...") doesn't work properly when there is a space in the path. (Note os.system can work with ('"...."') but anyhow)
Had the OP tried their program from a cmd prompt they'd have seen the error clearly.
C:\carp>type blah.py
import os
os.system(R"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe")
C:\carp>python blah.py
'C:\Program' is not recognized as an internal or external command,
operable program or batch file.
C:\carp>
So it's fine for os.system("calc.exe") (there calc.exe is in the path environment variable). Or for os.system(R"c:\windows\system32\calc.exe"). There's no space in that path.
C:\>md "aa bb cc"
C:\>copy c:\windows\system32\calc.exe "c:\aa bb cc\cccalc.exe"
1 file(s) copied.
This works (Given file "c:\aa bb cc\cccalc.exe" )
import os
os.chdir(R"c:\aa bb cc")
os.system("cccalc.exe")
Other options are subprocess.run and subprocess.popen.
Is that trying to execute C:\Documents with arguments of "and", "Settings/flow_model/flow.exe"?
Also, you might consider subprocess.call().
There are loads of different solutions, and the results will strongly depend on:
the OS you are using: Windows, Cygwin, Linux, MacOS
the python version you are using: Python2 or Python3x
As I have discovered some things that are claimed to work only in Windows, doesn't, probably because I happen to use Cygwin which is outsmarting the OS way to deal with Windows paths. Other things only work in pure *nix based OS's or in Python2 or 3.
Here are my findings:
Generally speaking, os.system() is the most forgiving method.
os.startfile() is the least forgiving. (Windows only && if you're lucky)
subprocess.Popen([...]) not recommended
subprocess.run(winView, shell=True) the recommended way!
Remembering that using subprocess for anything may pose a security risk.
Try these:
import os, subprocess
...
winView = '/cygdrive/c/Windows/explorer.exe %s' % somefile
...
# chose one of these:
os.system(winView)
subprocess.Popen(['/cygdrive/c/Windows/explorer.exe', 'somefile.png'])
subprocess.run(winView, shell=True)
Q: Why would you want to use explorer in Windows?
A: Because if you just want to look at the results of some new file, explorer will automatically open the file with whatever default windows program you have set for that file type. So no need to re-specify the default program to use.
That's the correct usage, but perhaps the spaces in the path name are messing things up for some reason.
You may want to run the program under cmd.exe as well so you can see any output from flow.exe that might be indicating an error.
for the above question this solution works.
just change the path to where your executable file is located.
import sys, string, os
os.chdir('C:\\Downloads\\xpdf-tools-win-4.00\\xpdf-tools-win-4.00\\bin64')
os.system("C:\\Downloads\\xpdf-tools-win-4.00\\xpdf-tools-win-4.00\bin64\\flowwork.exe")
'''import sys, string, os
os.chdir('C:\\Downloads\\xpdf-tools-win-4.00\\xpdf-tools-win-4.00\\bin64')
os.system(r"C:\\Downloads\\xpdf-tools-win-4.00\\xpdf-tools-win-4.00\bin64\\pdftopng.exe test1.pdf rootimage")'''
Here test1.pdf rootimage is for my code .

Categories