How to pass float argv parameters to another script? - python

I am trying to run a simple script named test using python test in the terminal in order to call two other scripts.
This is the script I am running
#!/usr/bin/env python
import sys
import rospy
import subprocess
import time
from geometry_msgs.msg import Twist
from std_msgs.msg import Empty
subprocess.call("./takeoff_sim")
time.sleep(2)
subprocess.call("./forward_sim" + sys.argv[5.0] + sys.argv[2.0])
But I am getting the following error :
Traceback (most recent call last):
File "test", line 15, in <module>
subprocess.call(["./forward_sim"] + sys.argv[5.0] + sys.argv[2.0])
TypeError: list indices must be integers, not float
In this case both arguments need to a float thus, I cant just change them to int 0.5 should be the first argument and 2.0 the second one. Here is the forward_sim script:
#!/usr/bin/env python
import sys
import rospy
from geometry_msgs.msg import Twist
def commander(speed, time):
movement_publisher = rospy.Publisher('cmd_vel', Twist , queue_size=10)
rospy.init_node("bebop_commander") #Use log_level=rospy.DEBUG to see debug messages
rate = rospy.Rate(20) # 20hz
counter = 0.0
movement_cmd = Twist()
while not rospy.is_shutdown():
movement_cmd.linear.x = speed
movement_cmd.linear.y = 0
movement_cmd.linear.z = 0
movement_cmd.angular.x = 0
movement_cmd.angular.y = 0
movement_cmd.angular.z = 0
rospy.logdebug("Publishing")
counter += 0.05
movement_publisher.publish(movement_cmd)
rate.sleep()
if counter >= time:
break
if __name__ == '__main__':
speed = float(sys.argv[0])
time = float(sys.argv[1])
rospy.logdebug("Adelante") # Use rospy.logdebug() for debug messages.
print("Adelante")
if speed > 0:
rospy.logdebug("Velocidad = %s m/s", speed)
print("Velocidad =",speed," m/s",)
else:
raise ValueError("Falta parametro de velocidad o el valor es incorrecto")
if time > 0 :
rospy.logdebug("Tiempo = %s s", time)
print("Tiempo =" ,time, " s")
else:
raise ValueError("Falta parametro de tiempo o el valor es incorrecto")
try:
commander(speed, time)
except rospy.ROSInterruptException:
pass

sys.argv is only for receiving arguments. To pass values as arguments to another script, you need only convert them to strings and add them directly to the command line.
subprocess.call(["./forward_sim", str(5.0), str(2.0)])
When the other script receives them, it needs to convert each string back to a float:
# This is forward_sim
arg1 = float(sys.argv[1])
arg2 = float(sys.argv[2])
Note that sys.argv[0] is the name of the script itself, not the first argument.

Related

How to see the error frames of a CAN network with Python-CAN

I wrote the program below,
can = CAN("can0", bitrate=50000, listen_only=True, error_reporting=True)
while True:
msg = can.recv()
print "Msg: ", msg
But it only displays the standard S or Extended X flags even though when I run the command in Terminal to check the network activity, I can see that the error counter is increasing.
import can
import CAN
import time
import logging
#logging.basicConfig(level=logging.DEBUG)
print("Initializing Listener")
can1 = CAN('can0', bitrate=500000, listen_only=True, err_reporting=True)
#print "Bus is : ", can1.bus.get_can_bus()
can1.bus.set_filters(can_filters=[{"can_mask":0x7FF, "can_id":0x00000000, "extended":False}])
CAN_ERR_FLAG = 0x20000000
while 1:
msg = can1.recv()
if (msg.arbitration_id & CAN_ERR_FLAG) == CAN_ERR_FLAG:
print "Can Error Caught"
elif msg.is_error_frame:
print "Finally Error Frame"
How can I read the error-frames of the CAN-bus ?
Things work fine when I use commnad candump -e any,0:0,#FFFFFFFF
Use Python - 3
import binascii
channel_name = "vcan0"
socketID = socket.socket(socket.AF_CAN, socket.SOCK_RAW, socket.CAN_RAW)
# socketID.setsockopt(socket.SOL_CAN_RAW, socket.CAN_RAW_ERR_FILTER, 0x1FFFFFFF)
error = socketID.bind((channel_name,))
print(binascii.hexlify(socketID.recv(32)))

How to stop a script within a script

I'm looking to control a script via Zigbee/XBee using X-CTU. I've created a script named zb_control.py. Now I'm trying to start and stop another script within this script. A script adxl345test.py is used to collect data from an attached accelerometer on my Raspberry Pi.
The idea behind the zb_control.py script is that I run it and then if I type "run" in X-CTU the script will start running adxl345test.py and collect data.
I'm trying to create a script within a script that can also be stopped again and then still have the zb_control.py running ready to recieve new input from X-CTU.
As you can tell I've tried different things:
import serial, time, sys, os, subprocess
from subprocess import check_call
from subprocess import call
while True:
ser=serial.Serial('/dev/ttyUSB0',9600,timeout=2)
inc=ser.readline().strip()
if inc=='run':
print("---------------")
print("Collecting data")
print("---------------")
p = subprocess.Popen("/home/pi/adxl345test.py", stdout=subprocess.PIPE, shell=True)
elif inc=='stop':
# check_call(["pkill", "-9", "-f", adxl345test.py])
# serial.write('\x03')
# os.system("pkill –f adxl345test.py")
# call(["killall", "adxl345test.py"])
p.kill()
print("-----------------------")
print("Script has been stopped")
print("-----------------------")
I got it to run and it's now collecting data properly. However now the problem is stopping the adxl345test.py again. As you can tell from the script from above I'm using p.kill() but the script doesn't stop collecting data. When I type "stop" in XCTU my zb_control.py does print the print-commands but the p.kill() isn't being executed. Any suggestions?
I've tried using p.terminate() alone and together with p.kill() aswell as the commands by themselves however it doesn't stop the adxl345test.py script. I can tell that the .csv-file is still increasing in size and therefore the script must still be collecting data.
Here is the adxl345test.py script for those interested:
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Example on how to read the ADXL345 accelerometer.
# Kim H. Rasmussen, 2014
import sys, math, os, spidev, datetime, ftplib
# Setup SPI
spi = spidev.SpiDev()
#spi.mode = 3 <-- Important: Do not do this! Or SPI won't work as intended, or even at all.
spi.open(0,0)
spi.mode = 3
# Read the Device ID (should be xe5)
id = spi.xfer2([128,0])
print 'Device ID (Should be 0xe5):\n'+str(hex(id[1])) + '\n'
# Read the offsets
xoffset = spi.xfer2([30 | 128,0])
yoffset = spi.xfer2([31 | 128,0])
zoffset = spi.xfer2([32 | 128,0])
accres = 2
accrate = 13
print 'Offsets: '
print xoffset[1]
print yoffset[1]
# print str(zoffset[1]) + "\n\nRead the ADXL345 every half second:"
# Initialize the ADXL345
def initadxl345():
# Enter power saving state
spi.xfer2([45, 0])
# Set data rate to 100 Hz. 15=3200, 14=1600, 13=800, 12=400, 11=200, 10=100 etc.
spi.xfer2([44, accrate])
# Enable full range (10 bits resolution) and +/- 16g 4 LSB
spi.xfer2([49, accres])
# Enable measurement
spi.xfer2([45, 8])
# Read the ADXL x-y-z axia
def readadxl345():
rx = spi.xfer2([242,0,0,0,0,0,0])
#
out = [rx[1] | (rx[2] << 8),rx[3] | (rx[4] << 8),rx[5] | (rx[6] << 8)]
# Format x-axis
if (out[0] & (1<<16 - 1 )):
out[0] = out[0] - (1<<16)
# out[0] = out[0] * 0.004 * 9.82
# Format y-axis
if (out[1] & (1<<16 - 1 )):
out[1] = out[1] - (1<<16)
# out[1] = out[1] * 0.004 * 9.82
# Format z-axis
if (out[2] & (1<<16 - 1 )):
out[2] = out[2] - (1<<16)
# out[2] = out[2] * 0.004 * 9.82
return out
# Initialize the ADXL345 accelerometer
initadxl345()
# Read the ADXL345 every half second
timetosend = 60
while(1):
with open('/proc/uptime','r') as f: # get uptime
uptime_start = float(f.readline().split()[0])
uptime_last = uptime_start
active_file_first = "S3-" + str(pow(2,accrate)*25/256) + "hz10bit" + str(accres) + 'g' + str(datetime.datetime.utcnow().strftime('%y%m%d%H%M')) $
active_file = active_file_first.replace(":", ".")
wStream = open('/var/log/sensor/' + active_file,'wb')
finalcount = 0
print "Creating " + active_file
while uptime_last < uptime_start + timetosend:
finalcount += 1
time1 = str(datetime.datetime.now().strftime('%S.%f'))
time2 = str(datetime.datetime.now().strftime('%M'))
time3 = str(datetime.datetime.now().strftime('%H'))
time4 = str(datetime.datetime.now().strftime('%d'))
time5 = str(datetime.datetime.now().strftime('%m'))
time6 = str(datetime.datetime.now().strftime('%Y'))
axia = readadxl345()
wStream.write(str(round(float(axia[0])/1024,3))+','+str(round(float(axia[1])/1024,3))+','+str(round(float(axia[2])/1024,3))+','+time1+','+ti$
# Print the reading
# print axia[0]
# print axia[1]
# print str(axia[2]) + '\n'
# elapsed = time.clock()
# current = 0
# while(current < timeout):
# current = time.clock() - elapsed
with open('/proc/uptime', 'r') as f:
uptime_last = float(f.readline().split()[0])
wStream.close()
def doftp(the_active_file):
session = ftplib.FTP('192.0.3.6','sensor3','L!ghtSp33d')
session.cwd("//datalogger//")
file = open('/var/log/sensor/' + active_file, 'rb') # file to send
session.storbinary('STOR' + active_file, file) # send the file
file.close()
session.quit
My suggestions:
If you're doing something at a specified interval, you're probably better off using threading.Timer rather than checking the time yourself.
As I said in the comment, you can check for an exit condition instead of brutally killing the process. This also allows to properly clean up what you need.
Those time1...time6 really don't look nice, how about a list? Also, time2, time3, time4, time5, time6 are not used.
You don't actually need strftime to get hour, day, month, year, etc. They're already there as attributes.
You can do something like:
cur_time = datetime.datetime.now()
cur_hour = cur_time.hour
cur_minute = cur_time.minute
...And so on, which is a bit better. In this specific case it won't matter, but if you start measuring milliseconds, the time will be slightly different after a few lines of code, so you should store it and use it from the variable.
As for the rest, if you want an example, here I check that a file exists to determine whether to stop or not. It's very crude but it should give you a starting point:
from threading import *
from os.path import exists
def hello():
print('TEST') # Instead of this, do what you need
if (exists('stop_file.txt')):
return
t = Timer(0.5, hello)
t.start()
hello()
Then in the other create you create the stop file when you want it to stop (don't forget to add a line to remove it before starting it again).

Unpack ValueError in Python

I was making a site component scanner with Python. Unfortunately, something goes wrong when I added another value to my script. This is my script:
#!/usr/bin/python
import sys
import urllib2
import re
import time
import httplib
import random
# Color Console
W = '\033[0m' # white (default)
R = '\033[31m' # red
G = '\033[1;32m' # green bold
O = '\033[33m' # orange
B = '\033[34m' # blue
P = '\033[35m' # purple
C = '\033[36m' # cyan
GR = '\033[37m' # gray
#Bad HTTP Responses
BAD_RESP = [400,401,404]
def main(path):
print "[+] Testing:",host.split("/",1)[1]+path
try:
h = httplib.HTTP(host.split("/",1)[0])
h.putrequest("HEAD", "/"+host.split("/",1)[1]+path)
h.putheader("Host", host.split("/",1)[0])
h.endheaders()
resp, reason, headers = h.getreply()
return resp, reason, headers.get("Server")
except(), msg:
print "Error Occurred:",msg
pass
def timer():
now = time.localtime(time.time())
return time.asctime(now)
def slowprint(s):
for c in s + '\n':
sys.stdout.write(c)
sys.stdout.flush() # defeat buffering
time.sleep(8./90)
print G+"\n\t Whats My Site Component Scanner"
coms = { "index.php?option=com_artforms" : "com_artforms" + "link1","index.php?option=com_fabrik" : "com_fabrik" + "ink"}
if len(sys.argv) != 2:
print "\nUsage: python jx.py <site>"
print "Example: python jx.py www.site.com/\n"
sys.exit(1)
host = sys.argv[1].replace("http://","").rsplit("/",1)[0]
if host[-1] != "/":
host = host+"/"
print "\n[+] Site:",host
print "[+] Loaded:",len(coms)
print "\n[+] Scanning Components\n"
for com,nme,expl in coms.items():
resp,reason,server = main(com)
if resp not in BAD_RESP:
print ""
print G+"\t[+] Result:",resp, reason
print G+"\t[+] Com:",nme
print G+"\t[+] Link:",expl
print W
else:
print ""
print R+"\t[-] Result:",resp, reason
print W
print "\n[-] Done\n"
And this is the error message that comes up:
Traceback (most recent call last):
File "jscan.py", line 69, in <module>
for com,nme,expl in xpls.items():
ValueError: need more than 2 values to unpack
I already tried changing the 2 value into 3 or 1, but it doesn't seem to work.
xpls.items returns a tuple of two items, you're trying to unpack it into three. You initialize the dict yourself with two pairs of key:value:
coms = { "index.php?option=com_artforms" : "com_artforms" + "link1","index.php?option=com_fabrik" : "com_fabrik" + "ink"}
besides, the traceback seems to be from another script - the dict is called xpls there, and coms in the code you posted...
you can try
for (xpl, poc) in xpls.items():
...
...
because dict.items will return you tuple with 2 values.
You have all the information you need. As with any bug, the best place to start is the traceback. Let's:
for com,poc,expl in xpls.items():
ValueError: need more than 2 values to unpack
Python throws ValueError when a given object is of correct type but has an incorrect value. In this case, this tells us that xpls.items is an iterable an thus can be unpacked, but the attempt failed.
The description of the exception narrows down the problem: xpls has 2 items, but more were required. By looking at the quoted line, we can see that "more" is 3.
In short: xpls was supposed to have 3 items, but has 2.
Note that I never read the rest of the code. Debugging this was possible using only those 2 lines.
Learning to read tracebacks is vital. When you encounter an error such as this one again, devote at least 10 minutes to try to work with this information. You'll be repayed tenfold for your effort.
As already mentioned, dict.items() returns a tuple with two values. If you use a list of strings as dictionary values instead of a string, which should be split anyways afterwards, you can go with this syntax:
coms = { "index.php?option=com_artforms" : ["com_artforms", "link1"],
"index.php?option=com_fabrik" : ["com_fabrik", "ink"]}
for com, (name, expl) in coms.items():
print com, name, expl
>>> index.php?option=com_artforms com_artforms link1
>>> index.php?option=com_fabrik com_fabrik ink

Return a tuple from a function and place into another function python

This description may be a bit complicated so I will try to keep it short.
I have the following code that is working correctly...
def singlelist():
from datetime import datetime
from subprocess import Popen
from subprocess import PIPE
output=Popen(["sar","-r"], stdout=PIPE).communicate()[0]
date=datetime.now()
date=str(date).split()[0]
listtimeval=[]
for line in output.split('\n'):
if line == '' or 'Average' in line or 'kb' in line or 'Linux' in line or 'RESTART' in line:
pass
else:
(time,ampm,field1,field2,field3,field4,field5,field6,field7) = line.split()
listtimeval.append((time + " "+ ampm + "," + field3).split(','))
updatelist= [ [str(date) + " " +x[0],x[1]] for x in listtimeval]
return updatelist
val=singlelist()
...notice how time,ampm,etc are not defined previously...
I am trying to make this more dynamic as the output of sar will not always have the same number of columns.
What I want to do is this...
def fields(method):
if method == '-r':
nf = (time,ampm,field1,field2,field3,field4,field5,field6,field7)
return nf
def singlelist(nf):
from datetime import datetime
from subprocess import Popen
from subprocess import PIPE
output=Popen(["sar","-r"], stdout=PIPE).communicate()[0]
date=datetime.now()
date=str(date).split()[0]
listtimeval=[]
for line in output.split('\n'):
if line == '' or 'Average' in line or 'kb' in line or 'Linux' in line or 'RESTART' in line:
pass
else:
nf = line.split()
listtimeval.append((time + " "+ ampm + "," + field3).split(','))
updatelist= [ [str(date) + " " +x[0],x[1]] for x in listtimeval]
return updatelist
method='-r'
nf=fields(method)
val=singlelist(nf)
However I am getting this...
Traceback (most recent call last):
File "./Logic.py", line 110, in <module>
nf=fields(method)
File "./Logic.py", line 58, in fields
nf = (time,ampm,field1,field2,field3,field4,field5,field6,field7)
NameError: global name 'time' is not defined
How can I accomplish this?
You haven't defined time in your fields function. Well, none of (time,ampm,field1,field2,field3,field4,field5,field6,field7) is defined in that function...
You don't use nf in singlelist, except to reallocate it. What are you trying to achieve ?
You could modify fields to accept the parameters (time,ampm,field1,field2,field3,field4,field5,field6,field7) along your method argument, but how would you define them? You would still have to call fields from singlelist.
Following up on Pierre's answer: you can assign TO an undeclared variable (implicitly creating it), you cannot assign FROM it without getting an undefined variable error.
You also seem to be making that poor function do an awful lot of unrelated things - loading modules, calling subprocesses, parsing and reparsing data. It might be easier to understand and maintain if you break it up as follows:
import datetime
from itertools import izip
from subprocess import Popen, PIPE
def call_sar(options, columns):
sar = Popen(["sar"]+options, stdout=PIPE) # create subprocess
res = sar.communicate()[0] # get stdout text
data = res.splitlines()[3:-1] # grab the relevant lines
return (dict(izip(columns, row.split())) for row in data)
def get_system_stats(mode, fmt=None):
modes = { # different ways to call sar, and the values returned by each
"all_cpus": ('-r', 'time ampm cpu user_pct nice_pct system_pct iowait_pct steal_pct idle_pct'),
"each_cpu": ('-P', 'time ampm cpu user_pct nice_pct system_pct iowait_pct steal_pct idle_pct'),
"mem": ('-r', 'time ampm memfree_kb memused_kb memused_pct buffers_kb cached_kb commit_kb commit_pct active_kb inactive_kb'),
"swap": ('-S', 'time ampm swapfree_kb swapused_kb swapused_pct swapcad_kb swapcad_pct'),
"all_io": ('-b', 'time ampm ts read_ts write_ts read_bs write_bs'),
"each_io": ('-p -d', 'time ampm dev ts read_ss write_ss avg_req_sz avg_queue_sz avg_wait'),
"switch": ('-w', 'time ampm proc_s switch_s'),
"queue": ('-q', 'runq_sz plist_sz avg_load_1 avg_load_5 avg_load_15 blocked')
}
if mode in modes:
options, columns = modes[mode]
data = call_sar(options.split(), columns.split())
if fmt is None:
# return raw data (list of dict)
return list(data)
else:
# return formatted data (list of str)
return [fmt.format(**d) for d in data]
else:
raise ValueError("I don't know mode '{}'".format(mode))
Now you can easily define your function like so:
def single_list():
today = datetime.datetime.now().date()
fmt = "{} {} {} {}".format(today, '{time}', '{ampm}', '{memused_pct}')
return get_system_stats("mem", fmt)
Note: I am writing this on a Windows 7 machine, so I don't have sar and can't actually run-test it - it has no syntax errors, and I think it should work properly as-is, but it may need minor tweaking.

'str' object is not callable TypeError

In my code I am trying to extract some data from a file. I am getting this error when I am trying to run my code on line 61. My code here:
from datetime import date
from math import floor;
from adjset_builder import adjset_builder
def check_and_update(d,start,end,log):
# print start,end;
if start in d:
if end in d[start]:
log.write("{0}-{1}\n".format(start, end))
if d[start][end] == 1:
print "one found"
d[start][end] += 1
def build_dictionary(my_adjset,my_list,factor,outfile,log):
log.write("building dictionary:\n");
window_size = int(floor(len(my_list)*factor));
if window_size<2:
log.write("too small\n")
return;
log.write('Total:{0},windowsize:{1}\n'.format(len(my_list),window_size));
log.write("Window at place: 0,")
for i in xrange(window_size):
j = i+1;
while j<window_size:
check_and_update(my_adjset, my_list[i][1], my_list[j][1],log);
j=j+1
i=1;
while i<=len(my_list)-window_size:
log.write("{0},".format(i))
j=i;
k=i+window_size-1;
while j<k:
check_and_update(my_adjset, my_list[i][1], my_list[j][1],log);
j+=1
i += 1
log.write("\nDictionary building done\n")
def make_movie_list(infilename,factor):
log=open('log.txt','w');
outfile=open(infilename.split('.')[0]+"_plot_"+str(factor)+".txt",'w');
f=open(infilename,'r');
my_adjset=dict()
adjset_builder('friends.txt', my_adjset);
count =1
while True:
string = f.readline();
if string=='':
break;
log.write("count:{0}\n".format(count))
count += 1
[movie,freunde] = string.split('=');
freunde = freunde.split(';')
mylist=[]
for i in freunde:
[user_id,date] = i.split(' ');
[yy,mm,dd] = date.split('-');
# l=list((date(int(yy),int(mm),int(dd)),user_id))
mylist.append([date(int(yy),int(mm),int(dd)),user_id]); ## line 61
log.write("list built");
print mylist
break;
# build_dictionary(my_adjset, mylist, factor,outfile,log)
del(mylist);
print 'Done'
log.close();
outfile.close();
f.close();
print count
if __name__ == '__main__':
make_movie_list('grades_processed.txt',.5)
However when I tried to simulate the same thing in 'Console' I do not get any error:
dd='12'
mm='2'
yy='1991'
user_id='98807'
from datetime import date
from datetime import date
l=list((date(int(yy),int(mm),int(dd)),user_id))
l [datetime.date(1991, 2, 12), '98807']
Might be something very silly but I am a beginner so can not seem to notice the mistake. Thank you!
This makes date a function:
from datetime import date
This makes date a string:
[user_id,date] = i.split(' ');
You get a TypeError now, since date is no longer a function:
mylist.append([date(int(yy),int(mm),int(dd)),user_id]);
One way to avoid this error is to import modules instead of functions:
import datetime as dt
mylist.append([dt.date(int(yy),int(mm),int(dd)),user_id])
or more succinctly,
mylist.append([dt.date(*date.split('-')), user_id])
PS: Remove all those unnecessary semicolons!
You have a variable called date, rename it so that it doesn't shadow the date function from datetime.

Categories