Hi, I am using the Ping1D echosounder and altimeter to measure ice growth in a tank. I have been trying to get the code below to run — it successfully ran through once, but since then the script has failed to run and gives the following Type Error: ‘NoneType’ object is not subscriptable. It sometimes works and populates the profile_data array created by get_profile() when just running the commands in the console, but every time I try to run the script it fails.
indent preformatted text by 4 spaces
myPing = Ping1D()
ping_S = myPing.connect_serial('/dev/tty.usbserial-DM022A5O', 115200)
myPing.set_speed_of_sound(1481000)
myPing.set_mode_auto(0)
myPing.set_range(0,1000)
myPing.set_gain_setting(4)
myPing.set_ping_interval(5000)
distp = []
confp = []
timerp = []
data = myPing.get_profile()
pro = []
for i in data['profile_data']:
pro.append(i)
perfil = np.array(pro,ndmin=2).T
z = np.array(np.linspace(0,data['scan_length'],200),ndmin=2).T
count = 0
while(count<2):
data = myPing.get_profile()
distp.append(data['distance'])
print(data['distance'])
pro = []
for i in data['profile_data']:
pro.append(i)
zi = np.array(np.linspace(0,data['scan_length'],200),ndmin=2).T
perfil = np.append(perfil,np.array(pro,ndmin=2).T,axis=1)
z = np.append(z,np.array(zi,ndmin=2),axis=1)
t.sleep(1)
print("next")
I’ve checked the initialize function and it is returning True each time. The get_profile is definitely failing frequently, and I am a bit concerned by this. I’ve run the simple code below to try problem solving where things begin going wrong. It ran successfully through three times, and then failed (no changes were made to the script — I just ran it four times in a row and it failed on the fourth run) throwing the “TypeError: ‘NoneType’ object is not subscriptable” for the data[‘profile_data’] line.
As I said, get_profile may fail returning None.
You should check the output if valid or not and recall the request, remember that ping-python is a high level library, so it tries to abstract the sensor functionality, but communication errors are still a thing.
You should do:
data = None
while not data:
data = myPing.get_profile()
time.sleep(1)
Since your TypeError here is about a NoneType object (None) not being subscriptable, your try-except block doesn’t actually do anything except add a tiny bit of delay from overhead (the call to get_profile doesn’t try to do any subscripting, that happens later when you do data[...]).
I would strongly suggest using @patrickelectric’s solution as it makes sure that a NoneType object can never reach the code where you’re trying to access parts of the data. It might be worth making a wait_profile function so that you can be sure that (or perhaps this is worth being added to the ping-python library if it’s a common usage requirement?).
As an example:
def wait_profile(ping, verbose_limit=10):
""" Waits for and returns a successful Ping profile read.
'verbose_limit' determines the minimum number of waits to notify about.
Setting the value to 0 notifies even when no waits were required.
"""
count = 0
while "reading unsuccessful":
data = ping.get_profile()
if data is None:
count += 1
time.sleep(1)
else:
break
if count >= verbose_limit:
print('waited ' + str(count) + ' times')
return data
although it may be helpful to reduce the sleep time if you consistently have only a single wait each call.