variable referenced before assignment: Python - python

I'm trying to get data from raspberry pi 3 to Azure
The script reads data from Raspberry Pi3, which is connect via bluetooth to sensors and takes several values.
Unfortunately i am getting an error, when I run it
"local variable 'temperature' referenced before assignment"
def iothub_client_sample_run():
msgs=[]
for address, name in list(devices.items()):
try:
client = iothub_client_init()
if client.protocol == IoTHubTransportProvider.MQTT & (name == "Flower care"):
msg_txt_formatted = MSG_TXT % (
temperature,
sunlight,
moisture,
fertility)
message = IoTHubMessage(msg_txt_formatted)
# optional: assign ids
message.temperature_id = "%d" % temperature
client.send_event_async(message, send_confirmation_callback, devices.items())
print ( "IoTHubClient.send_event_async accepted message {} for transmission to IoT Hub.".format(devices.items()) )
return msgs
while 1:
msgs=iothub_client_sample_run()
for msg in msgs:
print msg['topic']
print msg['payload']
(result, mid)=mqttc.publish(msg['topic'],msg['payload'])
print ( "Send status: %s" % status )
time.sleep(10)
mqttc.disconnect()
except IoTHubError as iothub_error:
print ( "Unexpected error %s from IoTHub" % iothub_error )
return
except KeyboardInterrupt:
print ( "IoTHubClient sample stopped" )
print_last_message_time(client)

The error message here is pretty clear.
Remember that Python reads and executes code one line at a time so if you have a variable stated after the function that uses it then it is going to throw an error. Juggle your code around to put your variables before they are called and you shouldn't have any problems with this error again.

Related

Python socket server new line issue

so I am making a socket server in python but every time a message is sent it does a new line like this
Rank: Admin
Rank Password: **Censored**
Nickname: SomeoneElse
[Admin
] Testusername
: hello
but what I want it to Receive is
[Admin] Testusername: hello
but every time the code is asking for the nickname rank and message with %s it does a new line here is the code being used
def rank(conn, prefix="Rank: "):
conn.send(prefix)
return conn.recv(512)
def nickname(conn, prefix="Nickname: "):
conn.send(prefix)
return conn.recv(512)
rank = rank(conn)
nickname = nickname(conn)
message = conn.recv(512)
if message:
reply = "[%s] %s: %s" % (rank, nickname, message)
broadcast(reply, conn)
else:
remove(conn)
def broadcast(message, connection):
for cons in bc:
if cons != connection:
try:
cons.sendall(message)
except:
cons.close()
remove(cons)
def remove(connection):
if connection in bc:
bc.remove(connection)
that is the code to the message system why is it doing a new line every time %s is used? btw I removed the other code cause its irrelevant to my question
I changed nickname to "nickname" so and it showed this
[Admin
] nickname: hi

Error on socket.recv (Python)

I got a small python program that communicates with an EV3 robot (lego's robot) via BT. The program sends the EV3 a number 1/2 or 3, the robot makes a predefined movement and send back 'A' to indicate that the movement is done and that it is ready for next command.
The system works great but once in a while the python app crushes with this error message:
'An established connection was aborted by the software in your host machine.' this comes from socket.recv that is called inside btListener() thread.
The relevant python parts:
import bluetooth
from gmail import *
import re
from gtts import gTTS
from time import sleep
import pygame
import serial
import thread
import os
import ftplib
from StringIO import StringIO
from blynkapi import Blynk
def a(): #Send 'a' to 'Status' mailbox
print "Send a to robot"
for i in commandA:
client_sock.send(chr(i))
sleep(1)
def b(): # Send 'b' to 'Status' mailbox
def c(): # Send 'c' to 'Status' mailbox
def clear(): # Send clear array to 'Status' mailbox
for i in clearArray:
client_sock.send(chr(i))
def btListener():
# Listen for end of run reply from the EV3
global ev3Flag, listenFlag
while True:
if listenFlag and (not ev3Flag):
try:
data = client_sock.recv(1024) #Check if EV3 is ready for new command
if data[-2] == 'A':
ev3Flag = True
print "Received 'Ready' from EV3 "
sleep(1)
except Exception as e:
print(e)
print "Failed to read data from socket"
def queueHandler():
# Read next command from QueueArray, call sendFunc and clear the queue
global ev3Flag, listenFlag, queueArray
while True:
if len(queueArray) > 0 and ev3Flag:
sendFunc(queueArray[0])
queueArray.pop(0)
def sendFunc(cmd):
#Send the next command on QueueArray to the EV3
global ev3Flag, listenFlag
if cmd == 1:
try:
ev3Flag = False
listenFlag = False
a()
listenFlag = True
sleep(3)
clear() # clear the EV3 btsocket with a default message
except Exception as e:
print "Error on sendFunc cmd = 1"
print(e)
elif cmd == 2:
try:
except Exception as e:
elif cmd == 3:
try:
except Exception as e:
if __name__ == "__main__":
# Blynk setup
blynk = Blynk(auth_token)
switch1 = Blynk(auth_token, pin = "V0")
switch2 = Blynk(auth_token, pin = "V1")
switch3 = Blynk(auth_token, pin = "V2")
print "Blynk connected"
queueArray = [] # Queue array to hold incoming commands
listenFlag = True # Listen to message from EV3
ev3Flag = True # EV3 ready for new command flag
# BT CONNECTION WITH EV3 #
print "Searching for BT connections: "
nearby_devices = bluetooth.discover_devices()
for bdaddr in nearby_devices:
print bdaddr + " - " + bluetooth.lookup_name(bdaddr)
if target_name == bluetooth.lookup_name(bdaddr):
target_address = bdaddr
break
server_sock = bluetooth.BluetoothSocket(bluetooth.RFCOMM)
port = 1
server_sock.bind(("", port))
server_sock.listen(1)
client_sock, address = server_sock.accept()
print "Accepted connection from ", address
if target_address is not None:
print "found target bluetooth device with address ", target_address
else:
print "could not find target bluetooth device nearby"
# END BT CONNECTION WITH EV3 #
try:
thread.start_new_thread(queueHandler, ())
except Exception as e: print(e)
try:
thread.start_new_thread(btListener, ())
except Exception as e: print(e)
while True:
res1 = switch1.get_val()
res2 = switch2.get_val()
res3 = switch3.get_val()
if (int)(res1[0]) == 1:
print "Add 1 to queue"
queueArray.append(1)
if (int)(res2[0]) == 1:
print "Add 2 to queue"
queueArray.append(2)
if (int)(res3[0]) == 1:
print "Add 3 to queue"
queueArray.append(3)
Edit 1:
I tested it a bit more and it seems that the crush happens when the program tries to recv data and send data the same time. (via the clear() or a()/b()/c() functions), could that be the situation?
I'm new to sockets so the first solution that comes in mind is create a flag to limit the action of the socket, is there a better/smarter way to keep that from happening?
Edit 2:
I moved the 'listenFlag = True' line inside sendFunc() to after my call to clear() and it seems to solve the problem which was probably due to the python program trying to receive and sand at the same time.
I moved the 'listenFlag = True' line inside sendFunc() to after my call to clear() and it seems to solve the problem which was probably due to the python program trying to receive and sand at the same time.

TypeError: 'int' object has no attribute '__getitem__' - Error recieved in IRC weather bot in Python

Okay, so I've got a bit of Python IRC Bot code, and I recently added a weather command to it, but it doesn't seem to work... heres the code
# Import some necessary libraries.
import socket
import time
import httplib
def commands(nick,channel,message):
if message.find('!test')!=-1:
ircsock.send('PRIVMSG %s :%s: test complete\r\n' % (channel,nick))
elif message.find('!help')!=-1:
ircsock.send('PRIVMSG %s :%s: My other command is test.\r\n' % (channel,nick))
elif message.find('!sex')!=-1:
ircsock.send('PRIVMSG %s :%s: But why?\r\n' % (channel,nick))
elif message.find('!quit')!=-1:
ircsock.send('QUIT :For the bones of the weak shall support me\r\n')
die('Quit command given')
elif message.find('!op')!=-1:
ircsock.send('MODE %s +o :%s\n' % (channel,nick))
elif message.find('!deop')!=-1:
ircsock.send('MODE %s -o :%s\n' % (channel,nick))
elif message.find('!weather')!=-1:
tmp = message.find(':!weather')
city = tmp[1].strip()
reqest_str = '/laika_zinas/?city=' + city
c = httplib.HTTPConnection("www.1188.lv")
c.request("GET", reqest_str)
ra = c.getresponse()
datas = ra.read()
temp, wind = tpars(datas)
ircsock.send('PRIVMSG %s :%s: [+] Temp: '+ temp +' C | Wind: '+ wind +' m/s' % (channel,nick))
c.close()
# Some basic variables used to configure the bot
server = "n0cht.bawx.net" # Server
channel = "#python" # Channel
botnick = "PyleDrivr" # Your bots nick
def ping(ircmsg): # This is our first function! It will respond to server Pings.
ircsock.send("PONG "+ ircmsg +"\n")
print("Ping replied\n\r")
def sendmsg(chan , msg): # This is the send message function, it simply sends messages to the channel.
ircsock.send("PRIVMSG "+ chan +" :"+ msg +"\n")
def joinchan(chan): # This function is used to join channels.
ircsock.send("JOIN "+ chan +"\n")
ircsock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
ircsock.connect((server, 6667)) # Here we connect to the server using the port 6667
ircsock.send("USER "+ botnick +" "+ botnick +" "+ botnick +" :PyleDrivr\n") # user authentication
ircsock.send("NICK "+ botnick +"\n") # here we actually assign the nick to the bot
joinchan(channel) # Join the channel using the functions we previously defined
while 1: # Be careful with these! it might send you to an infinite loop
ircmsg = ircsock.recv(2048) # receive data from the server
ircmsg = ircmsg.strip('\n\r') # removing any unnecessary linebreaks.
print(ircmsg) # Here we print what's coming from the server
if ircmsg.find(' PRIVMSG ')!=-1:
nick=ircmsg.split('!')[0][1:]
channel=ircmsg.split(' PRIVMSG ')[-1].split(' :')[0]
commands(nick,channel,ircmsg)
if ircmsg.find("PING :") != -1: # if the server pings us then we've got to respond!
ping(ircmsg)
Now, when I run the bot, it works just fine, but then this happens when I issue the command:
<wh0r3[mint]> !weather 99654
* PyleDrivr has quit (Client exited)
And here's what the term shows:
:wh0r3[mint]!~wh0r3#n0cht-D1D272D.gci.net PRIVMSG #lobby :!weather 99654
Traceback (most recent call last):
File "pyledrivr.py", line 65, in <module>
commands(nick,channel,ircmsg)
File "pyledrivr.py", line 22, in commands
city = tmp[1].strip()
TypeError: 'int' object has no attribute '__getitem__'
I have no idea what this means or how to fix it. and ideas?
This line:
tmp = message.find(':!weather')
assigns an integer to tmp: the position at which the string ':!weather' was found in message (see find). It may not even be found at all, since you check in the line above that '!weather' is in message, not ':!weather'.
Then you try and access tmp[1]. But tmp is just a number; it doesn't have a [1].
If you want to get the substring of message that follows '!weather', you could do this:
city = message[message.find('!weather')+8:].strip()
(8 being the length of '!weather')
Or you might find it easier to use split:
city = message.split('!weather')[1].strip()

How do I recover from a serialException using pySerial

I have an application that reads and transmits data to a device connected via USB. I'm using pySerial to facilitate this communication. Everything works fine until the USB cable is unplugged from the PC and an exception is thrown. Once the cable is plugged back in, I can't seem to recover and reconnect to my device. The only way for me to recover is to close down the application and unplug and plug the cable in again. Any help in understanding what's going on would be much appreciated.
This is basic test code that I'm useing to help me understand the process.
# Class used to communicate with USB Dongle
import serial
import time
import sys
class LPort:
def __init__(self, port=0):
"initialize the LPort class"
self.error = ""
self.traffic = ""
self.dest = None
if port == None:
self.simulation = True
else:
self.simulation = False
self.port = port # serial port we should use
self.reset()
self.time = time.time()
def reInit(self):
self.close()
def reset(self):
"flush port, reset the LPort, initialize LPort"
if self.simulation:
r = "LPort simulator"
else:
self.port.flushInput()
self.port.flushOutput()
self.fail = False
self.command("/H1")
self.dest = None
r = "reset"
self.error = ""
self.traffic = ""
return r
def status(self):
"return accumulated status info, reset collection"
s = self.error
self.error = ""
return s
def data(self):
"return accumulated traffic data, reset collection"
s = self.traffic
self.traffic = ""
return s
def set_dest(self, addr):
"set the destination address (if necessary)"
if addr != self.dest:
self.dest = addr
self.command("/O")
r = self.command("/D%02X" % addr)
if r != "*":
self.dest = None
self.error += r
else:
r = True
return r
def checksum(self, bytes):
"calculate the CRC-8 checksum for the given packet"
crc_table = [
# this table is taken from the CP rectifier code
0x00,0x07,0x0E,0x09,0x1C,0x1B,0x12,0x15,0x38,0x3F,
0x36,0x31,0x24,0x23,0x2A,0x2D,0x70,0x77,0x7E,0x79,
0x6C,0x6B,0x62,0x65,0x48,0x4F,0x46,0x41,0x54,0x53,
0x5A,0x5D,0xE0,0xE7,0xEE,0xE9,0xFC,0xFB,0xF2,0xF5,
0xD8,0xDF,0xD6,0xD1,0xC4,0xC3,0xCA,0xCD,0x90,0x97,
0x9E,0x99,0x8C,0x8B,0x82,0x85,0xA8,0xAF,0xA6,0xA1,
0xB4,0xB3,0xBA,0xBD,0xC7,0xC0,0xC9,0xCE,0xDB,0xDC,
0xD5,0xD2,0xFF,0xF8,0xF1,0xF6,0xE3,0xE4,0xED,0xEA,
0xB7,0xB0,0xB9,0xBE,0xAB,0xAC,0xA5,0xA2,0x8F,0x88,
0x81,0x86,0x93,0x94,0x9D,0x9A,0x27,0x20,0x29,0x2E,
0x3B,0x3C,0x35,0x32,0x1F,0x18,0x11,0x16,0x03,0x04,
0x0D,0x0A,0x57,0x50,0x59,0x5E,0x4B,0x4C,0x45,0x42,
0x6F,0x68,0x61,0x66,0x73,0x74,0x7D,0x7A,0x89,0x8E,
0x87,0x80,0x95,0x92,0x9B,0x9C,0xB1,0xB6,0xBF,0xB8,
0xAD,0xAA,0xA3,0xA4,0xF9,0xFE,0xF7,0xF0,0xE5,0xE2,
0xEB,0xEC,0xC1,0xC6,0xCF,0xC8,0xDD,0xDA,0xD3,0xD4,
0x69,0x6E,0x67,0x60,0x75,0x72,0x7B,0x7C,0x51,0x56,
0x5F,0x58,0x4D,0x4A,0x43,0x44,0x19,0x1E,0x17,0x10,
0x05,0x02,0x0B,0x0C,0x21,0x26,0x2F,0x28,0x3D,0x3A,
0x33,0x34,0x4E,0x49,0x40,0x47,0x52,0x55,0x5C,0x5B,
0x76,0x71,0x78,0x7F,0x6A,0x6D,0x64,0x63,0x3E,0x39,
0x30,0x37,0x22,0x25,0x2C,0x2B,0x06,0x01,0x08,0x0F,
0x1A,0x1D,0x14,0x13,0xAE,0xA9,0xA0,0xA7,0xB2,0xB5,
0xBC,0xBB,0x96,0x91,0x98,0x9F,0x8A,0x8D,0x84,0x83,
0xDE,0xD9,0xD0,0xD7,0xC2,0xC5,0xCC,0xCB,0xE6,0xE1,
0xE8,0xEF,0xFA,0xFD,0xF4,0xF3]
for i in range(len(bytes)):
b = int(bytes[i])
if i == 0: chksum = crc_table[b]
else: chksum = crc_table[chksum ^ b]
return chksum
def command(self, cmd):
"transmit distinct commands to unit, and accept response"
if self.simulation:
r = "*"
else:
try:
self.port.write(cmd + chr(13))
except serial.serialutil.SerialTimeoutException:
r = "/TO"
return r
except:
print "Unexpected error:", sys.exc_info()[0]
r = "/Unknown"
return r
r = ""
eol = False
while True:
c = self.port.read(1)
if not c:
r = "/FAIL " + r + " " + cmd
self.error = r
break
else:
r += c
ordc = ord(c)
if ordc == 13 or ordc == 42:
break
return r
def checkRawDataForErrors(self, raw, errors = []):
errorCodes = {'/SNA':'Slave Not Acknowledging',
'/I81':'Busy, Command Ignored',
'/I88':'Connection Not Open',
'/I89':'Invalid Command Argument',
'/I8A':'Transmit Not Active',
'/I8F':'Invalid Command',
'/I90':'Buffer Overflow',
'/DAT':'Data Error',
'/BADPEC':'Bad PEC Value',
'/NO_MRC':'No Master Read Complete Signal',
'/FAIL':'General Failure',
'/LEN':'Data Length Error'}
for ekey, eval in errorCodes.items():
if ekey in raw:
errors.append(eval)
return errors
# self-testing module
if __name__ == "__main__":
com = serial.Serial(port=4, baudrate=115200, timeout=1, xonxoff=0)
if com:
port = LPort(com)
print port
time.sleep(5)
port = LPort(com)
print "/V =", port.command("/V")
print "/V", port.data(), port.status()
print "/O =", port.command("/O")
print "/O", port.data(), port.status()
print "/A =", port.command("/A")
print "/A", port.data(), port.status()
print "/L =", port.command("/L")
print "/L", port.data(), port.status()
com.close()
else:
print "cannot open com port"
UPDATE:
The following is the code around the creatfile() in serialwin32.py which returns the following message:
serial.serialutil.SerialException: could not open port COM5: [Error 2] The system cannot find the file specified.
self.hComPort = win32.CreateFile(port,
win32.GENERIC_READ | win32.GENERIC_WRITE,
0, # exclusive access
None, # no security
win32.OPEN_EXISTING,
win32.FILE_ATTRIBUTE_NORMAL | win32.FILE_FLAG_OVERLAPPED,
0)
if self.hComPort == win32.INVALID_HANDLE_VALUE:
self.hComPort = None # 'cause __del__ is called anyway
raise SerialException("could not open port %s: %s" % (self.portstr, ctypes.WinError()))
Assuming your device is well-behaved, all you must do is this:
close your serial port (serial.Serial instance)
find the COMX name of your port again
open the serial port
The 2nd part is problematic because Windows tries to be clever. In your case the following happens:
USB device is connected and is assigned name COM2
Your program opens the device
USB disconnects
USB reconnects quickly before your program noticed that device died
Windows sees that COM2 is busy and assigns a different name to this USB device
(optional) your program closes the device
your program tries to open COM2 again, but there's no hardware at that name
The are way to get around Windows being clever -- you can specifically assign fixed COMX name to this device in Device Manager, COM ports, your port, advanced options.
Another option is to detect device dying very fast and closing the file handle. If you are lucky then by the time device reconnects original COM2 is free again.
Yet another option is to use a USB-serial converter from another manufacturer that uses another driver. Somehow COMX letter assignment is driver-specific. Better drivers may give you a stable name.
I've come across this problem as well. Sometimes my program has locked up when the device is plugged in again.
NB. I have fixed the COMx name of the port as mentioned by #qarma
I've rearranged my program so that as soon as an exception is thrown from the read() or write() methods of Serial I stop calling those methods.
I then have a function which periodically retries opening the port to try to detect when the device has been plugged in again.
This function creates a new instance of Serial with the same parameters as the original and tries to open it:
def try_to_open_new_port(self):
ret = False
test = serial.Serial(baudrate=9600, timeout=0, writeTimeout=0)
test.port = self.current_port_name
try:
test.open()
if test.isOpen():
test.close()
ret = True
except serial.serialutil.SerialException:
pass
return ret
A return of True indicates that the port is present once again.

How to do scheduled sending of email with django-mailer

I'm making a django app that needs to be able to make emails and then send these out at a given time. I was thinking i could use django-mailer to put things in que and then send it of. But even though theire sample case list, lists that this is a feature, I cant seem to find out how.
What I need is to be able to set a 'when_to_send' field in the message model of django-mailer, and when the cron job fires the send_mail function this needs to filter out the ones that has a 'when_to_send' date that is greater than the current time...
def send_all():
"""
Send all eligible messages in the queue.
"""
lock = FileLock("send_mail")
logging.debug("acquiring lock...")
try:
lock.acquire(LOCK_WAIT_TIMEOUT)
except AlreadyLocked:
logging.debug("lock already in place. quitting.")
return
except LockTimeout:
logging.debug("waiting for the lock timed out. quitting.")
return
logging.debug("acquired.")
start_time = time.time()
dont_send = 0
deferred = 0
sent = 0
try:
for message in prioritize():
if DontSendEntry.objects.has_address(message.to_address):
logging.info("skipping email to %s as on don't send list " % message.to_address)
MessageLog.objects.log(message, 2) # ### avoid using literal result code
message.delete()
dont_send += 1
else:
try:
logging.info("sending message '%s' to %s" % (message.subject.encode("utf-8"), message.to_address.encode("utf-8")))
core_send_mail(message.subject, message.message_body, message.from_address, [message.to_address])
MessageLog.objects.log(message, 1) # ### avoid using literal result code
message.delete()
sent += 1
except (socket_error, smtplib.SMTPSenderRefused, smtplib.SMTPRecipientsRefused, smtplib.SMTPAuthenticationError), err:
message.defer()
logging.info("message deferred due to failure: %s" % err)
MessageLog.objects.log(message, 3, log_message=str(err)) # ### avoid using literal result code
deferred += 1
finally:
logging.debug("releasing lock...")
lock.release()
logging.debug("released.")
logging.info("")
logging.info("%s sent; %s deferred; %s don't send" % (sent, deferred, dont_send))
logging.info("done in %.2f seconds" % (time.time() - start_time))
Anyone see how to customize this function to don't send email's where the message.when_to_send field is greater than the current time?
You need to implement the cron job for django-mailer:
* * * * * (cd $PINAX; /usr/local/bin/python2.5 manage.py send_mail >> $PINAX/cron_mail.log 2>&1)
And then in engine.py line 96:
# Get rid of "while True:"
while not Message.objects.all():
# Get rid of logging.debug("sleeping for %s seconds before checking queue again" % EMPTY_QUEUE_SLEEP)
# Get rid of sleep
send_all()
You can just add another clause to the conditionals under your message processing loop (you will also need to import datetime at the top of your file):
for message in prioritize():
if DontSendEntry.objects.has_address(message.to_address):
logging.info("skipping email to %s as on don't send list " % message.to_address)
MessageLog.objects.log(message, 2) # ### avoid using literal result code
message.delete()
dont_send += 1
elif message.when_to_send > datetime.datetime.now():
continue
else:
try:
... the rest of your code ...

Categories

Resources