Using Applescript to fire python script - python

I'm trying to use Applescript to fire a python script. When I fire it from terminal, everything works fine, but when I fire from Applescript, it appears to run but nothing happens.
I've tried all manner of combinations for everything I can find in searches and other posts for using "python file.py" or "/usr/bin/python file.py" with "#!/usr/bin/env python" and "#!/usr/bin/python".
If I enter "which python" in terminal, I get "/usr/bin/python"
Right now I have both scripts broken down to their base components. I'll eventually be using Applescript to pass a file path into python using sys.argv[1] (which is why I'm using Applescript to fire the python script) but I'm not even that far along yet as the below doesn't work yet.
Applescript
do shell script "/usr/bin/python $HOME/Desktop/test.py"
Python
#!/usr/bin/python
import sys
import os
# The notifier function
def notify(title, subtitle, message):
t = '-title {!r}'.format(title)
s = '-subtitle {!r}'.format(subtitle)
m = '-message {!r}'.format(message)
os.system('terminal-notifier {}'.format(' '.join([m, t, s])))
# Calling the function
notify(title = 'Message Test',
subtitle = 'Test1:',
message = 'Test2')
sys.exit(0)
The python script sends a notifier message. Every time I run in terminal, I receive the message without issue. Every time I run the applescript to do as shell script it runs without error-ing in AS, but no message comes from Python.
Anyone have thoughts on where I've gone wrong?

Does it work for you if you use a full path to the binary? It worked for me in both BBEdit and Smile (script editor). My path is:
/Applications/terminal-notifier-2.0.0/terminal-notifier.app/Contents/MacOS/terminal-notifier
So I used:
#!/usr/bin/python
import sys
import os
# The notifier function
def notify(title, subtitle, message):
t = '-title {!r}'.format(title)
s = '-subtitle {!r}'.format(subtitle)
m = '-message {!r}'.format(message)
os.system('/Applications/terminal-notifier-2.0.0/terminal-notifier.app/Contents/MacOS/terminal-notifier {}'.format(' '.join([m, t, s])))
# Calling the function
notify(title = 'Message Test',
subtitle = 'Test1:',
message = 'Test2')
sys.exit(0)

Related

How to check whether a shell command returned nothing or something

I am writing a script to extract something from a specified path. I am returning those values into a variable. How can i check whether the shell command has returned something or nothing.
My Code:
def any_HE():
global config, logger, status, file_size
config = ConfigParser.RawConfigParser()
config.read('config2.cfg')
for section in sorted(config.sections(), key=str.lower):
components = dict() #start with empty dictionary for each section
#Retrieving the username and password from config for each section
if not config.has_option(section, 'server.user_name'):
continue
env.user = config.get(section, 'server.user_name')
env.password = config.get(section, 'server.password')
host = config.get(section, 'server.ip')
print "Trying to connect to {} server.....".format(section)
with settings(hide('warnings', 'running', 'stdout', 'stderr'),warn_only=True, host_string=host):
try:
files = run('ls -ltr /opt/nds')
if files!=0:
print '{}--Something'.format(section)
else:
print '{} --Nothing'.format(section)
except Exception as e:
print e
I tried checking 1 or 0 and True or false but nothing seems to be working. In some servers, the path '/opt/nds/' does not exist. So in that case, nothing will be there on files. I wanted to differentiate between something returned to files and nothing returned to files.
First, you're hiding stdout.
If you get rid of that you'll get a string with the outcome of the command on the remote host. You can then split it by os.linesep (assuming same platform), but you should also take care of other things like SSH banners and colours from the retrieved outcome.
As perror commented already, the python subprocess module offers the right tools.
https://docs.python.org/2/library/subprocess.html
For your specific problem you can use the check_output function.
The documentation gives the following example:
import subprocess
subprocess.check_output(["echo", "Hello World!"])
gives "Hello World"
plumbum is a great library for running shell commands from a python script. E.g.:
from plumbum.local import ls
from plumbum import ProcessExecutionError
cmd = ls['-ltr']['/opt/nds'] # construct the command
try:
files = cmd().splitlines() # run the command
if ...:
print ...:
except ProcessExecutionError:
# command exited with a non-zero status code
...
On top of this basic usage (and unlike the subprocess module), it also supports things like output redirection and command pipelining, and more, with easy, intuitive syntax (by overloading python operators, such as '|' for piping).
In order to get more control of the process you run, you need to use the subprocess module.
Here is an example of code:
import subprocess
task = subprocess.Popen(['ls', '-ltr', '/opt/nds'], stdout=subprocess.PIPE)
print task.communicate()

How to execute commands with double quotes (net start "windows search") using python 'os' module?

When I execute simple command like "net start", I am getting output successfully as shown below.
Python script:
import os
def test():
cmd = ' net start '
output = os.popen(cmd).read()
print output
test()
Output:
C:\Users\test\Desktop\service>python test.py
These Windows services are started:
Application Experience
Application Management
Background Intelligent Transfer Service
Base Filtering Engine
Task Scheduler
TCP/IP NetBIOS Helper
The command completed successfully.
C:\Users\test\Desktop\service>
But When I execute long commands (for example : "net start "windows search") I am NOT getting any output.
Python script:
import os
def test():
cmd = ' net start "windows search" '
output = os.popen(cmd).read()
print output
test()
Output:
C:\Users\test\Desktop\service>python test.py
C:\Users\test\Desktop\service>
I have tried "net start \"windows search\" ". also. But same issue.
Can anyone guide me on this please?
From the documentation:
Deprecated since version 2.6: This function is obsolete. Use the subprocess module. Check especially the Replacing Older Functions with the subprocess Module section.
subprocess.Popen(['net', 'start', 'windows search'], ...)

Working with Command Prompt through Python

I want to make a script which opens a command prompt window and input commands into that prompt without any user interaction. I have been using the subprocess module with little success. What I have so far:
def subprocess_cmd(command):
process = Popen(command,stdout=PIPE, shell=True)
proc_stdout = process.communicate()[0].strip()
print proc_stdout
subprocess_cmd('"C:\system\cmd.exe" & C:\dir\mybat.bat & C:\dir\gdal_translate C:\dir2\mypdf.pdf C:\dir\mytif.tif')
Now it runs through without error, but nothing happens. There should be a .tif file in the dir2 folder but as I said, nothing appears. When I run through the command prompt myself, it works fine.
I think the problem is you are not calling the methods and constants from the subprocess class. This worked for me in Python 3:
import subprocess
def subprocess_cmd(command,c="C:\\Users\\Alex"):
process = subprocess.Popen(command,stdout=subprocess.PIPE,shell=True,cwd=c)
proc_stdout = process.communicate()[0].strip()
print(proc_stdout)
>>> subprocess_cmd('"cmd.exe" && "C:\\Users\\Alex\\test.bat"','C:\\Users\\Alex\\')
b'Microsoft Windows [Version 6.3.9600]\r\n(c) 2013 Microsoft Corporation. All rights reserved.\r\n\r\nC:\\Users\\Alex>\r\nC:\\Users\\Alex>mkdir thisisanewdirectory'
>>> subprocess_cmd('test.bat')
b'C:\\Users\\Alex>mkdir thisisanewdirectory'

running a python script on server

i have a python script on the server
#!/usr/bin/env python
import cgi
import cgitb; #cgitb.enable()
import sys, os
from subprocess import call
import time
import subprocess
form = cgi.FieldStorage()
component = form.getvalue('component')
command = form.getvalue('command')
success = True
print """Content-Type: text/html\n"""
if component=="Engine" and command=="Start":
try:
process = subprocess.Popen(['/usr/sbin/telepath','engine','start'], shell=False, stdout=subprocess.PIPE)
print "{ans:12}"
except Exception, e:
success = False
print "{ans:0}"
When I run this script and add the component and command parameters to be "Engine" and "Start" respectively - it starts the process and prints to the shell
"""Content-Type: text/html\n"""
{ans:12}
but most importantly - it starts the process!
however, when I run the script by POSTing to it, it returns {ans:12} but does not run the process which was the whole intention in the first place. Any logical explanation?
I suspect it's one of two things, firstly your process is probably running but your python code doesn't handle the output so do:
process = subprocess.Popen(['/usr/sbin/telepath','engine','start'], shell=False, stdout=subprocess.PIPE)
print process.stdout.read()
This is the most likely and explains why you see the output from the command line and not the browser, or secondly because the script is run through the browsers as the user apache and not with your userid check the permission for /usr/sbin/telepath.

How can I tell whether screen is running?

I am trying to run a Python program to see if the screen program is running. If it is, then the program should not run the rest of the code. This is what I have and it's not working:
#!/usr/bin/python
import os
var1 = os.system ('screen -r > /root/screenlog/screen.log')
fd = open("/root/screenlog/screen.log")
content = fd.readline()
while content:
if content == "There is no screen to be resumed.":
os.system ('/etc/init.d/tunnel.sh')
print "The tunnel is now active."
else:
print "The tunnel is running."
fd.close()
I know there are probably several things here that don't need to be and quite a few that I'm missing. I will be running this program in cron.
from subprocess import Popen, PIPE
def screen_is_running():
out = Popen("screen -list",shell=True,stdout=PIPE).communicate()[0]
return not out.startswith("This room is empty")
Maybe the error message that you redirect on the first os.system call is written on the standard error instead of the standard output. You should try replacing this line with:
var1 = os.system ('screen -r 2> /root/screenlog/screen.log')
Note the 2> to redirect standard error to your file.

Categories