EncodeError: <flask_mail.Message object at 0x7f044bf07410> is not JSON serializable - flask

My final code is looks like the following:
#client_route.route('/client/cat-<dir_code>/subscribe/<string:user_id>', methods=['POST'])
#only_client
#is_active_client
# #cache.cached(timeout=60)
def subscribe_abonent(user_id):
search_form = Search()
client_id = Client.query.filter_by(tele=session.get('client_phone') ,name=session.get('client_logged_in'), family=session.get('client_family')).first_or_404()
master = Abonent.query.filter_by(public_id=user_id, slug_direction=g.get('current_directory')).first_or_404()
client = Client.query.filter_by(id=client_id.id).first_or_404()
if session.get('client_is_not_subscriber'):
session.pop('client_is_not_subscriber')
session['client_is_subscriber'] = client.name + client.family + str(client.id)
socketio.emit('show_calendar', namespace='/masterCalendar-{}'.format(master.slug, master.public_id.replace('-','')))
if master.email is not None:
if master.subscribers_notifications:
date_now = datetime.now()
send_email(master.email, 'You got a new subscriber','client/newsletter/new_subscriber',master=master.name + ' ' + master.family, client=client.name + " " + client.family, sent=date_now)
#celery.task
def send_email(to, subject, template, **kwargs):
with current_app.app_context():
msg = Message(current_app.config['UBOOK_MAIL_SUBJECT_PREFIX'] + ' ' + subject,
sender=current_app.config['UBOOK_MAIL_SENDER'], recipients=[to])
msg.body = render_template(template + '.txt', **kwargs)
msg.html = render_template(template + '.html', **kwargs)
mail.send(msg)
Now everything is working fine, but celery not recognizing the task, the task runs inside the terminal just like your are sending email using Thread !!!
new_subscriber.txt:
Dear Vladimir, Here was {{master}}
You got a new subscriber:
Клиент: Sasha , Here was {{client}}
Получено: 2017-11-23 12:47:23 , Here was {{sent}}
Another thing that i forgot to mention that , if i removed the master, client and sent arguments and used delay() the code get freezed !!

Related

Unable to mqtt_client publish inside a class

I'm trying to use Paho MQTT Client and Multiprocessing to send temperature with defined interval. However, publish command is not working inside class. I've checked self.mqtt_client inside scheduler it has the Client object.
Is there anyone that can address problem for me?
Everything inside class is working except Scheduler.
def scheduler(self, topic, interval):
if interval != 0:
while True:
if topic == "temp":
print("Temperature published " + interval) #It's working.
self.mqtt_client.publish(topic, interval , 0 , False) #There is no error/output about this line
time.sleep(int(interval))
else:
pass
Class:
class Switcher:
config = None
mqtt_client = None
mqtt_connected = False
switches = {}
stages = {}
def __init__(self, config):
self.config = config
for switch_cfg in self.config['switches']:
self.switches[switch_cfg['topic_set']] = Switch(int(switch_cfg['gpio']), switch_cfg['topic_status'], switch_cfg['initial'])
def scheduler(self, topic, interval):
if interval != 0:
while True:
if topic == "temp":
print("Temperature published " + interval) #It's working.
self.mqtt_client.publish(topic, interval , 0 , False) #There is no error/output about this line
time.sleep(int(interval))
else:
pass
def mqtt_connect(self):
if self.mqtt_broker_reachable():
self.verbose('Connecting to ' + self.config['mqtt_host'] + ':' + self.config['mqtt_port'])
self.mqtt_client = mqtt.Client(self.config['mqtt_client_id'])
if 'mqtt_user' in self.config and 'mqtt_password' in self.config:
self.mqtt_client.username_pw_set(self.config['mqtt_user'], self.config['mqtt_password'])
self.mqtt_client.on_connect = self.mqtt_on_connect
self.mqtt_client.on_disconnect = self.mqtt_on_disconnect
self.mqtt_client.on_message = self.mqtt_on_message
try:
self.mqtt_client.connect(self.config['mqtt_host'], int(self.config['mqtt_port']), 10)
for switch_cfg in self.config['switches']:
self.mqtt_client.subscribe(switch_cfg['topic_set'], 0)
self.mqtt_client.loop_forever()
except:
self.error(traceback.format_exc())
self.mqtt_client = None
else:
self.error(self.config['mqtt_host'] + ':' + self.config['mqtt_port'] + ' not reachable!')
def mqtt_on_connect(self, mqtt_client, userdata, flags, rc):
self.mqtt_connected = True
for switch_ios in self.config['switches']:
self.mqtt_client.publish(self.config['station_status'], "available", 0, False)
self.mqtt_client.publish(switch_ios['topic_status'], self.switches[switch_ios['topic_set']].get_state(), 0, False)
temp_interval = 1
temp_process = multiprocessing.Process(target=self.scheduler, args=("temp",str(temp_interval),))
temp_process.start()
self.verbose('...mqtt_connected!')
def mqtt_broker_reachable(self):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.settimeout(5)
try:
s.connect((self.config['mqtt_host'], int(self.config['mqtt_port'])))
s.close()
return True
except socket.error:
return False
def start(self):
self.mqtt_connect()
You mqtt_connect function will never return.
self.mqtt_client.loop_forever() Will block until self.mqtt_client.disconnect() is called.
You should probably be using self.mqtt_client.loop_start() which will run the client loop on it's own thread in the background. You can call self.mqtt_client.loop_stop() when you want to shut the client down.

Error while closing the python serial port

" i am trying to read data from the serial connection and doing some stuff if it matches my string but its giving me errors when i close the serial connection port"
" for some reason i do not see this error if i use the serial.readline() method "
import time
import serial
from Queue import Queue
from threading import Thread
class NonBlocking:
def __init__(self, serial_connection, radio_serial_connection):
self._s = serial_connection
self._q = Queue()
self.buf = bytearray()
def _populateQueue(serial_connection, queue):
if type(serial_connection) == str:
return
self.s = serial_connection
while True:
i = self.buf.find(b"\n")
if i >= 0:
r = self.buf[:i + 1]
self.buf = self.buf[i + 1:]
queue.put(r)
while True:
i = max(1, min(2048, self.s.in_waiting))
data = self.s.read(i)
i = data.find(b"\n")
if i >= 0:
r = self.buf + data[:i + 1]
self.buf[0:] = data[i + 1:]
a = r.split('\r\n')
for item in a:
if item:
queue.put(item)
else:
self.buf.extend(data)
self._t = Thread(target=_populateQueue, args=(self._s, self._q))
self._t.daemon = True
self._t.start()
def read_all(self, timeout=None):
data = list()
if self._q.empty():
pass
while not self._q.empty():
data.append(self._q.get(block=timeout is not None, timeout=timeout))
return data
class SerialCommands:
def __init__(self, port, baudrate):
self.serial_connection = serial.Serial(port, baudrate)
self.queue_data = NonBlocking(self.serial_connection, '')
def read_data(self):
returned_info = self.queue_data.read_all()
return returned_info
def close_q(self):
self.serial_connection.close()
class qLibrary:
def __init__(self):
self.q = None
self.port = None
def close_q_connection(self):
self.q.close_q()
def establish_connection_to_q(self, port, baudrate=115200, delay=2):
self.delay = int(delay)
self.port = port
try:
if not self.q:
self.q = SerialCommands(self.port, int(baudrate))
except IOError:
raise AssertionError('Unable to open {0}'.format(port))
def verify_event(self, data, timeout=5):
timeout = int(timeout)
data = str(data)
# print data
while timeout:
try:
to_analyze = self.q.read_data()
for item in to_analyze:
print "item: ", item
if str(item).find(str(data)) > -1:
print "Found data: '{0}' in string: '{1}'".format(data, item)
except:
pass
time.sleep(1)
timeout -= 1
if __name__ == '__main__':
q1 = qLibrary()
q1.establish_connection_to_q('COM5')
q1.verify_event("ATE")
q1.close_q_connection()
" i expect the code to close the serial connection without any exceptions or errors "
the output is
Exception in thread Thread-1:
Traceback (most recent call last):
File "C:\Python27\Lib\threading.py", line 801, in __bootstrap_inner
self.run()
File "C:\Python27\Lib\threading.py", line 754, in run
self.__target(*self.__args, **self.__kwargs)
File "C:/Program Files (x86)/serialtest1.py", >line 27, in _populateQueue
data = self.s.read(i)
File "C:\Program Files (x86)\venv\lib\site->packages\serial\serialwin32.py", line 283, in read
ctypes.byref(self._overlapped_read))
TypeError: byref() argument must be a ctypes instance, not 'NoneType'
If you define your serial port with no timeout it will get the default setting timeout=None which means when you call serial.read(x) the code will block until you read x bytes.
If you never get those x bytes your code will get stuck in there waiting forever, or at least until you receive more data on the buffer to get the total number of bytes received equal to x.
If you mix that up with threading, I'm afraid you are quite likely closing the port while you are trying to read.
You can probably fix this issue just defining a sensible read timeout on your port or changing the way you read. The general advice is to set a timeout that works for your application and read at least the maximum number of bytes you expect. Reading your code, that seems to be what you wanted to do. If so, you forgot to set the timeout.
If you have a reason not to set a timeout or you want to keep your reading routine as it is, you can make your code work if you cancel reading before closing. You can do that with serial.cancel_read()

How to save result of a function into a string so it can be sent via email (using smtplib and MIME)?

I am new to Python and very much a rookie. I am trying to write a program that uses the requests module to make a request to the Dark Sky API for a weather forecast, and then uses smtplib to send that forecast in an email to myself. I have truncated my code to only show the relevant parts. I have been unable to find any answers so far so I apologise if this is a duplicate. The below code will print the function to the console without any issues, but when I try to assign it to the "body" variable and email it, the email is blank. Or if I use str(ds.current)) the email just has "none" as the body text.
How can I make it work so that the body text of the email contains the forecast that has been requested from the API? Many thanks in advance, and sorry for any rookie errors.
import requests
import json
import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
class Darksky():
r = requests.get('https://api.darksky.net/forecast/e01635ccacb5548e3d1fa40403bbb3a5/-45.0312,168.6626?units=ca')
wx_json = r.json()
def __init__(self, source):
self.source = source
print "\n", "-" * 20, source, "-" * 20, "\n"
def current(self):
def summary():
return "CURRENT WEATHER:"
x = self.wx_json['currently']['summary']
return x
# I have tried using print instead of return but that did not work either.
def temp():
return "TEMPERATURE:"
y = self.wx_json['currently']['temperature']
return y
summary()
temp()
ds = Darksky("DARKSKY WX")
fromaddr = "watsonthevirtualbutler#gmail.com"
toaddr = "matt#peakpixel.nz"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = "YOUR DAILY WEATHER, SIR."
body = ds.current()
# This is where I am trying to save the function result as a string that can be emailed.
# I have tried using "str(ds.current())" but that just returns "none".
print body
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP('smtp.gmail.com', 587)
server.starttls()
server.login(fromaddr, "virtualbutler")
text = msg.as_string()
msg = "CAN YOU HEAR ME, SIR?"
server.sendmail(fromaddr, toaddr, text)
server.quit()
Your summary() and temp() has two return operators, while only one return is acceptable. If you want your_function() to return few values, you can do something like: return {"first_parameter": "first_value", "second_parameter": "second_value"} and then call each value as your_function()["first_parameter"] or your_function()["second_parameter"]
Try following code and let me know the result:
class Darksky():
r = requests.get('https://api.darksky.net/forecast/e01635ccacb5548e3d1fa40403bbb3a5/-45.0312,168.6626?units=ca')
wx_json = r.json()
def __init__(self, source):
self.source = source
print "\n", "-" * 20, source, "-" * 20, "\n"
def current(self):
return "CURRENT WEATHER: {0}. TEMPERATURE: {1}".format(self.wx_json['currently']['summary'], self.wx_json['currently']['temperature'])
ds = Darksky("DARKSKY WX")
body = ds.current()

Get SOAP attachment

There is a lot of questions with same subject, but no replies, especially about receiving. There exist example how to send attachment, but I didn't found how to receive it.
Is there any solution on python for receiving attachments? I even agree to change my SOAP tool from suds to anything that will works.
Thank you in advance.
I solved it with suds.
def GetWithFile(self, client, servicename, modelthings):
func = client.get_suds_func('Retrieve' + servicename)
clientclass = func.clientclass({})
SoapClient = clientclass(func.client, func.method)
binding = func.method.binding.input
soap_xml = binding.get_message(func.method, [modelthings], {})
soap_xml.children[0].children[1].children[0].attributes.append(u'attachmentInfo="true"')
soap_xml.children[0].children[1].children[0].attributes.append(u'attachmentData="true"')
soap_xml.children[0].children[1].children[0].attributes.append(u'ignoreEmptyElements="true"')
SoapClient.last_sent(soap_xml)
plugins = PluginContainer(SoapClient.options.plugins)
plugins.message.marshalled(envelope=soap_xml.root())
if SoapClient.options.prettyxml:
soap_xml = soap_xml.str()
else:
soap_xml = soap_xml.plain()
soap_xml = soap_xml.encode('utf-8')
plugins.message.sending(envelope=soap_xml)
request = Request(SoapClient.location(), soap_xml)
request.headers = SoapClient.headers()
reply = SoapClient.options.transport.send(request)
print(reply)
Files = []
boundary = self.find_substring(reply.headers['content-type'], 'boundary="', '"')
if boundary is not "":
list_of_data = reply.message.split(boundary)
list_of_data.pop(0)
list_of_data.pop(len(list_of_data) - 1)
soap_body = '<SOAP-ENV:Envelope' + self.find_substring(list_of_data[0], '<SOAP-ENV:Envelope', '</SOAP-ENV:Envelope>') + '</SOAP-ENV:Envelope>'
for line in list_of_data[1:]:
File = SMFile()
Files.append(File)
File.filename = self.find_substring(line, 'Content-Location: ', '\r\n')
File.key = self.find_substring(line, 'Content-ID: ', '\r\n')
idx = line.index( 'Content-ID:' )
start_idx = line.index( '\r\n\r\n' , idx ) + len('\r\n\r\n')
fin_idx = line.rindex( '\r\n--', start_idx )
File.body = line[start_idx: fin_idx]
File.size = fin_idx - start_idx
else:
soap_body = '<SOAP-ENV:Envelope' + self.find_substring(reply.message, '<SOAP-ENV:Envelope', '</SOAP-ENV:Envelope>') + '</SOAP-ENV:Envelope>'
ctx = plugins.message.received(reply=soap_body)
soap_body = ctx.reply
if SoapClient.options.retxml:
answer = soap_body
else:
answer = SoapClient.succeeded(binding, soap_body)
dict = {}
self.FieldsToDict(answer.model.instance, dict)
return {u'body': answer, u'Files': Files}
Here we extract some low level of suds, being able to fix any field in envelope. Then, after reply was got, we parse all boundaries and receive as many files, as we got.

PySide, QTextEdit Append adding blank lines

I have this simple code: basically a tool to send some commands to cmd, and display the output from cmd in a QTextEdit.
Basically, it works.
The only problem that I have is that each time I click on send (with or without a new command), the text is appended but strange blank lines appears at the end of the QTextEdit. Even when i clear the "console", still have these lines.
Maybe it has something to do with the way I call the process, I don't know hence the need for help.
from PySide.QtCore import *
from PySide.QtGui import *
import sys
class MyWindow(QDialog):
def __init__(self, parent=None):
super(MyWindow, self).__init__(parent)
self.setWindowTitle("Send to CMD")
self.check1 = QCheckBox("Activate Variable")
self.variable = QLineEdit()
self.finalcommand = QLineEdit()
self.clearCommand = QPushButton("Clear")
self.sendCommand = QPushButton("Send")
self.clearOnSend = QCheckBox("Clear on Send")
self.process = QProcess()
self.console = QTextEdit(self)
layout = QVBoxLayout()
layout.addWidget(self.check1)
layout.addWidget(self.variable)
layout.addWidget(self.finalcommand)
layout.addWidget(self.clearOnSend)
layout.addWidget(self.clearCommand)
layout.addWidget(self.sendCommand)
layout.addWidget(self.console)
self.setLayout(layout)
self.connect(self.check1, SIGNAL("clicked()"), self.appendText)
self.variable.textChanged.connect(self.appendText)
self.clearCommand.clicked.connect(self.Clear)
self.sendCommand.clicked.connect(self.Send)
def appendText(self):
if self.check1.isChecked():
TEXT1 = "Dir" + ' ' + str(self.variable.text())
else:
TEXT1 = ""
self.finalcommand.setText(str(TEXT1))
def Clear(self):
if self.clearCommand.isEnabled():
self.console.clear()
def Send(self):
if self.clearOnSend.isChecked():
self.console.clear()
FCTS = "cmd.exe /c" + " " + str(self.finalcommand.text())
self.process.readyReadStandardOutput.connect(self.readConsole)
self.process.start(FCTS)
if not self.process.waitForStarted(0):
return False
if not self.process.waitForFinished(0):
return False
def readConsole(self):
#self.console.setText(str(self.process.readAllStandardOutput()))
self.console.append(str(self.process.readAllStandardOutput()))
app = QApplication(sys.argv)
form = MyWindow()
form.show()
app.exec_()
You probably want to use the string.rstrip() function instead of string.strip()
if you change
self.console.append(str(self.process.readAllStandardOutput()))
to
self.console.append(str([self.process.readAllStandardOutput()]))
you can see what is going on, hope this helps
def appendText(self):
if self.check1.isChecked():
TEXT1 = "Dir" + ' ' + str(self.variable.text())
else:
TEXT1 = ""
you have to remove the last line after else and just type pass
this way no new empty lines will be appended
def appendText(self):
if self.check1.isChecked():
TEXT1 = "Dir" + ' ' + str(self.variable.text())
else:
pass