Make Python module callable - python-2.7

need some help making the below a callable object for another script e.g scrape.run()
I'm not sure where to start any pointers?
scrape.py
from clint.textui import puts, colored
import subprocess, sys
from datetime import datetime
from time import sleep as sleep
today = datetime.now().strftime("%H:%M:%S")
multimon_ng = subprocess.Popen("rtl_fm -A lut -s 22050 -f 148.81250M | multimon-ng -t raw -a FLEX -f alpha /dev/stdin",
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=True)
while True:
try:
nextline = multimon_ng.stdout.readline()
if not nextline:
pass
else:
try:
flex, mdate, mtime, bitrate, other, capcode, o2, msg = nextline.split(" ", 7)
except ValueError:
print "invalid line", nextline
else:
puts(colored.yellow(capcode), newline=False)
puts(" [", newline=False)
puts(colored.green(mdate + " " + str(datetime.now().strftime('%H:%M'))), newline=False)
puts(" ]", newline=False)
puts(msg)
except KeyboardInterrupt:
print "exit"
multimon_ng.poll()

Add this to the bottom of the script.
if __name__ == "__main__":
function_you_wish_to_call_here()
Anything under the if statement will run when you call the script directly.

Related

awk command in subprocess.Popen - Getting Error

I am trying this code:This code work fine and gave me the output what i need .
import os,sys
import sitenamevalidation
import getpass
import subprocess
site_name = sys.argv[1]
def get_location(site_name):
site_name_vali = sitenamevalidation.sitenamevalidation(site_name)
if site_name_vali == True:
pass
else:
print("Sitename should be in this format [a-z][a-z][a-z][0-9][0-9] example abc54 or xyz50")
sys.exit(0)
site = site_name[:3].upper()
user =getpass.getuser()
path = os.path.join('/home/',user,'location.attr')
if os.path.exists(path) == True:
pass
else:
print("Not able to find below path "+path)
#p1 = subprocess.Popen(['awk', '/site/{getline; print}' , path] ,stdout=subprocess.PIPE)
p1 = subprocess.Popen(['awk', '/ABC/{getline; print}' , path] ,stdout=subprocess.PIPE)
output=p1.communicate()
print str(output[0].strip().lower())
if __name__ == "__main__":
get_location(site_name)
Main issue is if i use this below command
p1 = subprocess.Popen(['awk', '/ABC/{getline; print}' , path] ,stdout=subprocess.PIPE)
where ABC is static value in path it work fine and give me desired output but i wanted the value which user will enter (site in my code). When i am doing this
p1 = subprocess.Popen(['awk', '/site/{getline; print}' , path] ,stdout=subprocess.PIPE)
It is looking for site in that file which is not there.I want the value of site variable to go in that command rather the site itself.Tried different by putting quote , double quote but nothing seem to be working.

How to end animation after function completes

I am writing a simple program to keep an eye on a few Addresses.
I want a simple text cursor animation to run while the program does its thing. I've managed to do that. However, my problem is that after the function doing the scanning finishes the animation keeps going and won't stop until I hit the break key.
import os
import time
import sys
import itertools
import threading
hostname = [multiple site list]
def responder(hostname):
while True:
for item in hostname:
response = os.system("ping -q -c 1 -n > /dev/null 2>&1 " + item)
if response == 0:
time.sleep(2)
else:
print item, 'is DOWN!'
sys.exit()
def animate():
for c in itertools.cycle(['|', '\'']):
sys.stdout.write('\rscanning for bums > ' + c)
sys.stdout.flush()
time.sleep(0.1)
t = threading.Thread(target=animate)
t.start()
responder(hostname)
I know the code might be a little messy as I'm halfway through the project but any idea what it is I could change to make the animation stop when the responder function exits?
You need to pass a threading.Event to the animate function and set it when you want it to stop:
import os
import time
import sys
import itertools
import threading
hostname = ['bogus.org']
def responder(hostname, t, quit_flag):
while True:
for item in hostname:
response = os.system("ping -q -c 1 -n %s >> /dev/null 2>&1" % item)
if response == 0:
time.sleep(2)
else:
quit_flag.set()
t.join()
print "%s is DOWN!" % item
return
def animate(quit_flag):
for c in itertools.cycle(['|', '\'']):
if quit_flag.is_set():
print ""
break
sys.stdout.write('\rscanning for bums %s > %s' % (quit_flag.is_set(), c))
sys.stdout.flush()
time.sleep(0.1)
quit_flag = threading.Event()
t = threading.Thread(target=animate, args=(quit_flag,))
t.daemon = True
t.start()
responder(hostname, t, quit_flag)
I modified your responder function so that it sets the quit flag, joins the animate thread, prints the message, and then returns. This guarantees that the animate thread is finished before the message is printed.
I realized that trying to use a regular variable does not work because only the value gets passed to the animate function. If you do not want to use a threading.Event, you can use a single element array or some other object that will get passed by reference.

Python 2.7.11 getopt doesn't read the argument

In Python 2.7.13
We have the following python code to take the command line argument:
import sys
import csv
import os
import sys, getopt
import pandas as pd
print('Python version ' + sys.version)
print('Pandas version ' + pd.__version__)
def main():
SERVER_NAME=''
PORT_NAME=''
PASSWORD=''
try:
opts, args = getopt.getopt(sys.argv[1:],"hs:p:x:",["server=","port=","password="])
except getopt.GetoptError:
print 'help'
sys.exit(2)
for o, a in opts:
if o == '-h':
print '\n'+'-s / --server (required)'
print '\n'+'-p or --port (required)'
print '\n'+'-x or --password (required)'
sys.exit()
elif o in ("-s", "--server"):
SERVER_NAME = a
elif o in ("-p", "--port"):
PORT_NAME = a
elif o in ("-x", "--password"):
PASSWORD = a
else:
assert False, "No command line option. To see the options, plese use -h"
if __name__ == "__main__":
main()
print SERVER_NAME
dbServer=SERVER_NAME
However, when running the above code in the command line:
python test.py -s AAA -p BBB -x CCC
the following error will show up:
print SERVER_NAME
NameError: name 'SERVER_NAME' is not defined
Could any guru enlighten if anything is wrong here? Thanks.
SERVER_NAME is defined as a variable local to the main() function, si it is not visible in the global scope (the lines at the bottom of your code.
You could either make SERVER_NAME a global variable or move the code after the call to main() into main(). My preference would be the latter; when I write code with a CLI like this, I don't have any code after calling main() (I often have global setup code before that call, but none of that depends on what happens in the main function)
Here is what I mean by 'moving code into main':
dbServer = ''
def main():
global dbServer
SERVER_NAME=''
PORT_NAME=''
PASSWORD=''
try:
opts, args = getopt.getopt(sys.argv[1:],"hs:p:x:", ["server=","port=","password="])
except getopt.GetoptError:
print 'help'
sys.exit(2)
for o, a in opts:
if o == '-h':
print '\n'+'-s / --server (required)'
print '\n'+'-p or --port (required)'
print '\n'+'-x or --password (required)'
sys.exit()
elif o in ("-s", "--server"):
SERVER_NAME = a
elif o in ("-p", "--port"):
PORT_NAME = a
elif o in ("-x", "--password"):
PASSWORD = a
else:
assert False, "No command line option. To see the options, plese use -h"
print SERVER_NAME
dbServer=SERVER_NAME
if __name__ == "__main__":
main()

Trapping a shutdown event in Python

I posted a question about how to catch a "sudo shutdown -r 2" event in Python. I was sent to this thread: Run code in python script on shutdown signal .
I'm running a Raspberry Pi v2 with Jessy.
I have read about
signal
and have tried to follow the ideas in the above thread, but so far I have not been successful. Here is my code:
import time
import signal
import sys
def CloseAll(Code, Frame):
f = open('/mnt/usbdrive/output/TestSignal.txt','a')
f.write('Signal Code:' + Code)
f.write('Signal Frame:' + Frame)
f.write('\r\n')
f.close()
sys.exit(0)
signal.signal(signal.SIGTERM,CloseAll)
print('Program is running')
try:
while True:
#get readings from sensors every 15 seconds
time.sleep(15)
f = open('/mnt/usbdrive/output/TestSignal.txt','a')
f.write('Hello ')
f.write('\r\n')
f.close()
except KeyboardInterrupt:
f = open('/mnt/usbdrive/output/TestSignal.txt','a')
f.write('Done')
f.write('\r\n')
f.close()
The program runs in a "screen" session/window and reacts as expected to a CNTL-C. However, when I exit the screen session, leaving the program running, and enter "sudo shutdown -r 2", the Pi reboots as expected after 2 minutes, but the TestSignal.txt file does not show that the signal.SIGTERM event was processed.
What am I doing wrong? Or better yet, how can I trap the shutdown event, usually initiated by a cron job, and close my Python program running in a screen session gracefully?
When you do not try to await such an event, but in a parallel session send SIGTERMto that process (e.g. by calling kill -15 $PID on the process id $PID of the python script running) , you should see an instructive error message ;-)
Also the comment about the mount point should be of interest after you repaired the python errors (TypeError: cannot concatenate 'str' and 'int' objects).
Try something like:
import time
import signal
import sys
LOG_PATH = '/mnt/usbdrive/output/TestSignal.txt'
def CloseAll(Code, Frame):
f = open(LOG_PATH, 'a')
f.write('Signal Code:' + str(Code) + ' ')
f.write('Signal Frame:' + str(Frame))
f.write('\r\n')
f.close()
sys.exit(0)
signal.signal(signal.SIGTERM, CloseAll)
print('Program is running')
try:
while True:
# get readings from sensors every 15 seconds
time.sleep(15)
f = open(LOG_PATH, 'a')
f.write('Hello ')
f.write('\r\n')
f.close()
except KeyboardInterrupt:
f = open(LOG_PATH, 'a')
f.write('Done')
f.write('\r\n')
f.close()
as a starting point. If this works somehow on your system why not rewrite some portions like:
# ... 8< - - -
def close_all(signum, frame):
with open(LOG_PATH, 'a') as f:
f.write('Signal Code:%d Signal Frame:%s\r\n' % (signum, frame))
sys.exit(0)
signal.signal(signal.SIGTERM, close_all)
# 8< - - - ...
Edit: To further isolate the error and adapt more to production like mode, one might rewrite the code like this (given that syslog is running on the machine, which it should, but I never worked on devices of that kind):
#! /usr/bin/env python
import datetime as dt
import time
import signal
import sys
import syslog
LOG_PATH = 'foobarbaz.log' # '/mnt/usbdrive/output/TestSignal.txt'
def close_all(signum, frame):
"""Log to system log. Do not spend too much time after receipt of TERM."""
syslog.syslog(syslog.LOG_CRIT, 'Signal Number:%d {%s}' % (signum, frame))
sys.exit(0)
# register handler for SIGTERM(15) signal
signal.signal(signal.SIGTERM, close_all)
def get_sensor_readings_every(seconds):
"""Mock for sensor readings every seconds seconds."""
time.sleep(seconds)
return dt.datetime.now()
def main():
"""Main loop - maybe check usage patterns for file resources."""
syslog.syslog(syslog.LOG_USER, 'Program %s is running' % (__file__,))
try:
with open(LOG_PATH, 'a') as f:
while True:
f.write('Hello at %s\r\n' % (
get_sensor_readings_every(15),))
except KeyboardInterrupt:
with open(LOG_PATH, 'a') as f:
f.write('Done at %s\r\n' % (dt.datetime.now(),))
if __name__ == '__main__':
sys.exit(main())
Points to note:
the log file for the actual measurements is separate from the logging channel for operational alerts
the log file handle is safeguarded in context managing blocks and in usual operation is just kept open
for alerting the syslog channel is used.
as a sample for the message routing the syslog.LOG_USER on my system (OS X) gives me in all terminals a message, whilst the syslog.LOG_ERR priority message in signal handler only targets the system log.
should be more to the point during shutdown hassle (not opening a file, etc.)
The last point (5.) is important in case all processes receive a SIGTERM during shutdown, i.e. all want to do something (slowing things down), maybe screenalso does not accept any buffered input anymore (or does not flush), note stdout is block buffered not line buffered.
The decoupling of the output channels, should also ease the eventual disappearance of the mount point of the measurement log file.

how to run python script with crontab with proxy

I am trying to run a python script from bash script to upload files to a website using crontab. The script runs from terminal but doesn't work from crontab and the error is
"Error: <urlopen error [Errno -2] Name or service not known>"
The python script is:
#!/usr/bin/env python
from ConfigParser import ConfigParser
from mechanize import Browser, RobustFactory
import base64
from os.path import basename
import sys
import os
print(os.environ)
if __name__ == "__main__":
if len(sys.argv) != 2:
print "Error: 1 argument needed"
sys.exit(1)
#DATA FROM CFG FILE
url = "http:website"
cfn = "absolute_path/upload.cfg"
cfg = ConfigParser()
try:
cfg.read(cfn)
usr = cfg.get('Auth', 'user')
pwd = cfg.get('Auth', 'pass')
except Exception, e:
print "Error:", e
sys.exit(1)
if not usr or not pwd:
print "Error: username or password not valid."
sys.exit(1)
filename = sys.argv[1]
try:
br = Browser(factory=RobustFactory())
br.addheaders.append(('Authorization', 'Basic %s' % base64.encodestring('%s:%s' % (usr, pwd))))
br.open(url)
br.select_form(nr=1)
br.form.add_file(open(filename, 'rb'), 'text/plain', basename(filename))
br.submit()
print "File '%s' successfully uploaded" % filename
sys.exit(0)
except Exception, e:
print "Error:", e
sys.exit(1)
When I try to "print(os.environ)" in python script in the case of manual run and using crontab:
with crontab :
"{'MAILTO': '/var/mail/envclim', 'LANG': 'en_US.UTF-8', 'SHELL': '/bin/sh', 'XDG_RUNTIME_DIR': '/run/user/1000', 'SHLVL': '2', 'PYTHONPATH': '/usr/lib/python2.7/site-packages:/usr/lib/python2.7/site-packages/', 'OLDPWD': '/home/envclim/upload_sdswas', 'PWD': '/home/envclim/upload_sdswas/upload_scripts', 'LOGNAME': 'envclim', 'USER': 'envclim', 'HOME': '/home/envclim', 'PATH': '/bin:/usr/bin:/usr/local/bin:/usr/local/CDO/bin', 'XDG_SESSION_ID': '6', '_': '/usr/bin/python'}"
but in the manual case , there is the proxy, as the following:
{'HTTP_PROXY': 'http://10.51.51.51:80/', 'KDE_IS_PRELINKED': '1', 'ALL_PROXY': 'socks://10.51.51.51:80/', 'NO_PROXY': 'localhost,127.0.0.0/8,::1', 'GJS_DEBUG_OUTPUT': 'stderr', 'http_proxy': 'http://10.51.51.51:80/', 'FTP_PROXY': 'http://10.51.51.51:80/',----------}
In crontab, I add :
SHELL=/bin/sh
PATH=/bin:/usr/bin
PYTHONPATH=/usr/lib/python2.7/site-packages
MAILTO=/var/mail/envclim
I am using fedora19. I tried to disabled proxy, but the script didn't work at all.
please, can anyone solve this problem?
Thanks in advance
Zeinab
Thanks alot for your comments, I solved this problem by adding these lines in crontab:
PYTHONPATH=/usr/lib/python2.7/site-packages
HTTP_PROXY=http://10.51.51.51:80/
and in the bash file that used to run the python script:
export PYTHONPATH=$PYTHONPATH:/usr/lib/python2.7/site-packages/
export LD_LIBRARY_PATH=/lib:/usr/lib:/usr/local/lib:/usr/local/usr/lib