python AttributeError: 'mHID' object has no attribute 'dict' - python

I am trying to make a makeblock mblock implementation with python and i found this api on github but it uses python 2.7 and i am using python 3.8 so i am trying to configure the code so it can run on python 3.8 but i ran into an error which is
init mBot
bot
<lib.mBot.mSerial object at 0x02CE9898>
start with serial
<lib.mBot.mHID object at 0x02E2B310>
self.device = mHID()
'mHID' object has no attribute 'dict'
Exception in thread Thread-2:
self.start()
Traceback (most recent call last):
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 154, in __onRead
start with HID
--------------------
n = self.device.inWaiting()
<lib.mBot.mBot object at 0x002FF640>
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 96, in inWaiting
--------------------
Error in sys.excepthook:
buf = self.dict.device.read(64)
Traceback (most recent call last):
AttributeError: 'mHID' object has no attribute 'dict'
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 134, in excepthook
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\abdsak11\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
self.close()
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 142, in close
self.device.close()
self.run()
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 106, in close
File "C:\Users\abdsak11\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 870, in run
self.dict.device.close()
AttributeError: 'mHID' object has no attribute 'dict'
Original exception was:
Traceback (most recent call last):
File "c:/Users/abdsak11/OneDrive - Lärande/Dokument/GitHub/python-for-mbot/test.py", line 15, in <module>
self._target(*self._args, **self._kwargs)
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 163, in __onRead
bot.doMove(50,50)
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 179, in doMove
self.close()
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 142, in close
self.__writePackage(bytearray([0xff,0x55,0x7,0x0,0x2,0x5]+self.short2bytes(-leftSpeed)+self.short2bytes(rightSpeed)))
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 278, in short2bytes
self.device.close()
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 106, in close
return [ord(val[0]),ord(val[1])]
TypeError: ord() expected string of length 1, but int found
self.dict.device.close()
AttributeError: 'mHID' object has no attribute 'dict'
'mHID' object has no attribute 'dict'
Exception in thread Thread-1:
Traceback (most recent call last):
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 154, in __onRead
n = self.device.inWaiting()
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 96, in inWaiting
buf = self.dict.device.read(64)
AttributeError: 'mHID' object has no attribute 'dict'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\abdsak11\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 932, in _bootstrap_inner
self.run()
File "C:\Users\abdsak11\AppData\Local\Programs\Python\Python38-32\lib\threading.py", line 870, in run
self._target(*self._args, **self._kwargs)
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 163, in __onRead
self.close()
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 142, in close
self.device.close()
File "c:\Users\abdsak11\OneDrive - Lärande\Dokument\GitHub\python-for-mbot\lib\mBot.py", line 106, in close
self.dict.device.close()
AttributeError: 'mHID' object has no attribute 'dict'
So what i am trying to do is to control and upload code to my mbot via usb COM3 serial and thats the error that i am getting i tried everthing but its not working and i cant seem to figure out the cause of the error.
mbot.py
this is the main api that i found
import serial
import sys,time
import signal
from time import ctime,sleep
import glob,struct
from multiprocessing import Process,Manager,Array
import threading
import hid
class mSerial():
ser = None
def __init__(self):
print (self)
def start(self, port):
self.ser = serial.Serial(port,115200)
def device(self):
return self.ser
def serialPorts(self):
if sys.platform.startswith('win'):
ports = ['COM%s' % (i + 1) for i in range(256)]
elif sys.platform.startswith('linux') or sys.platform.startswith('cygwin'):
ports = glob.glob('/dev/tty[A-Za-z]*')
elif sys.platform.startswith('darwin'):
ports = glob.glob('/dev/tty.*')
else:
raise EnvironmentError('Unsupported platform')
result = []
for port in ports:
s = serial.Serial()
s.port = port
s.close()
result.append(port)
return result
def writePackage(self,package):
self.ser.write(package)
sleep(0.01)
def read(self):
return self.ser.read()
def isOpen(self):
return self.ser.isOpen()
def inWaiting(self):
return self.ser.inWaiting()
def close(self):
self.ser.close()
class mHID():
def __init__(self):
print (self)
def start(self):
print ("starting start \n\n")
self.manager = Manager()
print("manager pass \n\n")
self.dict = self.manager.dict()
print("dict pass \n\n")
self.dict.device = hid.device()
print("dict device pass \n\n")
self.dict.device.open(0x0416, 0xffff)
print("dict device open pass \n\n")
self.dict.device.hid_set_nonblocking(self.device,1)
print ("start")
self.buffer = []
self.bufferIndex = 0
def enumerate(self):
print ("enumerate")
for dev in self.dict.device.enumerate():
print ('------------------------------------------------------------')
print (dev.description())
def writePackage(self,package):
buf = []
buf += [0, len(package)]
for i in range(len(package)):
buf += [package[i]]
n = self.dict.device.write(buf)
sleep(0.01)
def read(self):
c = self.buffer[0]
self.buffer = self.buffer[1:]
return chr(c)
def isOpen(self):
return True
def inWaiting(self):
buf = self.dict.device.read(64)
l = 0
if len(buf)>0:
l = buf[0]
if l>0:
for i in range(0,l):
self.buffer += [buf[i+1]]
return len(self.buffer)
def close(self):
self.dict.device.close()
class mBot():
def __init__(self):
print ("init mBot")
signal.signal(signal.SIGINT, self.exit)
self.manager = Manager()
self.__selectors = self.manager.dict()
self.buffer = []
self.bufferIndex = 0
self.isParseStart = False
self.exiting = False
self.isParseStartIndex = 0
def startWithSerial(self, port):
self.device = mSerial()
self.device.start(port)
self.start()
def startWithHID(self):
self.device = mHID()
print ("self.device = mHID()\n \n")
self.device.start()
print ("self.device.start()\n \n")
self.start()
print ("self.start()\n \n")
def excepthook(self, exctype, value, traceback):
self.close()
def start(self):
sys.excepthook = self.excepthook
th = threading.Thread(target=self.__onRead,args=(self.onParse,))
th.start()
def close(self):
self.device.close()
def exit(self, signal, frame):
self.exiting = True
sys.exit(0)
def __onRead(self,callback):
while 1:
if(self.exiting==True):
break
try:
if self.device.isOpen()==True:
n = self.device.inWaiting()
for i in range(n):
r = ord(self.device.read())
callback(r)
sleep(0.01)
else:
sleep(0.5)
except Exception as ex:
print (str(ex))
self.close()
sleep(1)
def __writePackage(self,pack):
self.device.writePackage(pack)
def doRGBLed(self,port,slot,index,red,green,blue):
self.__writePackage(bytearray([0xff,0x55,0x9,0x0,0x2,0x8,port,slot,index,red,green,blue]))
def doRGBLedOnBoard(self,index,red,green,blue):
self.doRGBLed(0x7,0x2,index,red,green,blue)
def doMotor(self,port,speed):
self.__writePackage(bytearray([0xff,0x55,0x6,0x0,0x2,0xa,port]+self.short2bytes(speed)))
def doMove(self,leftSpeed,rightSpeed):
self.__writePackage(bytearray([0xff,0x55,0x7,0x0,0x2,0x5]+self.short2bytes(-leftSpeed)+self.short2bytes(rightSpeed)))
def doServo(self,port,slot,angle):
self.__writePackage(bytearray([0xff,0x55,0x6,0x0,0x2,0xb,port,slot,angle]))
def doBuzzer(self,buzzer,time=0):
self.__writePackage(bytearray([0xff,0x55,0x7,0x0,0x2,0x22]+self.short2bytes(buzzer)+self.short2bytes(time)))
def doSevSegDisplay(self,port,display):
self.__writePackage(bytearray([0xff,0x55,0x8,0x0,0x2,0x9,port]+self.float2bytes(display)))
def doIROnBoard(self,message):
self.__writePackage(bytearray([0xff,0x55,len(message)+3,0x0,0x2,0xd,message]))
def requestLightOnBoard(self,extID,callback):
self.requestLight(extID,8,callback)
def requestLight(self,extID,port,callback):
self.__doCallback(extID,callback)
self.__writePackage(bytearray([0xff,0x55,0x4,extID,0x1,0x3,port]))
def requestButtonOnBoard(self,extID,callback):
self.__doCallback(extID,callback)
self.__writePackage(bytearray([0xff,0x55,0x4,extID,0x1,0x1f,0x7]))
def requestIROnBoard(self,extID,callback):
self.__doCallback(extID,callback)
self.__writePackage(bytearray([0xff,0x55,0x3,extID,0x1,0xd]))
def requestUltrasonicSensor(self,extID,port,callback):
self.__doCallback(extID,callback)
self.__writePackage(bytearray([0xff,0x55,0x4,extID,0x1,0x1,port]))
def requestLineFollower(self,extID,port,callback):
self.__doCallback(extID,callback)
self.__writePackage(bytearray([0xff,0x55,0x4,extID,0x1,0x11,port]))
def onParse(self, byte):
position = 0
value = 0
self.buffer+=[byte]
bufferLength = len(self.buffer)
if bufferLength >= 2:
if (self.buffer[bufferLength-1]==0x55 and self.buffer[bufferLength-2]==0xff):
self.isParseStart = True
self.isParseStartIndex = bufferLength-2
if (self.buffer[bufferLength-1]==0xa and self.buffer[bufferLength-2]==0xd and self.isParseStart==True):
self.isParseStart = False
position = self.isParseStartIndex+2
extID = self.buffer[position]
position+=1
type = self.buffer[position]
position+=1
# 1 byte 2 float 3 short 4 len+string 5 double
if type == 1:
value = self.buffer[position]
if type == 2:
value = self.readFloat(position)
if(value<-255 or value>1023):
value = 0
if type == 3:
value = self.readShort(position)
if type == 4:
value = self.readString(position)
if type == 5:
value = self.readDouble(position)
if(type<=5):
self.responseValue(extID,value)
self.buffer = []
def readFloat(self, position):
v = [self.buffer[position], self.buffer[position+1],self.buffer[position+2],self.buffer[position+3]]
return struct.unpack('<f', struct.pack('4B', *v))[0]
def readShort(self, position):
v = [self.buffer[position], self.buffer[position+1]]
return struct.unpack('<h', struct.pack('2B', *v))[0]
def readString(self, position):
l = self.buffer[position]
position+=1
s = ""
for i in Range(l):
s += self.buffer[position+i].charAt(0)
return s
def readDouble(self, position):
v = [self.buffer[position], self.buffer[position+1],self.buffer[position+2],self.buffer[position+3]]
return struct.unpack('<f', struct.pack('4B', *v))[0]
def responseValue(self, extID, value):
self.__selectors["callback_"+str(extID)](value)
def __doCallback(self, extID, callback):
self.__selectors["callback_"+str(extID)] = callback
def float2bytes(self,fval):
val = struct.pack("f",fval)
return [ord(val[0]),ord(val[1]),ord(val[2]),ord(val[3])]
def short2bytes(self,sval):
val = struct.pack("h",sval)
return [ord(val[0]),ord(val[1])]
test.py
this is the test file that i am working with
from lib.mBot import *
if __name__ == "__main__":
bot = mBot()
print ("bot \n\n")
bot.startWithSerial("COM3")
print ("start with serial\n\n")
bot.startWithHID()
print ("start with HID \n\n")
print(f'--------------------\n')
print (bot)
print(f'--------------------\n')
bot.doMove(50,50)

I believe your trouble is here:
class mHID():
def __init__(self):
print (self)
def start(self):
# ...
self.dict = self.manager.dict()
# ...
def close(self):
self.dict.device.close()
You should always define your instance attributes in __init__(), at least with an initial value of None, even if you plan to change them later.
Additionally, whenever you have a situation where "A must be called before B", you should write the code to properly handle when B is called without A. In this case, what should close() do if start() was never called? For simplicity, I'm just having it do nothing, but you may consider raising an exception.
class mHID():
def __init__(self):
print (self)
self.dct = None
def start(self):
# ...
self.dct = self.manager.dict()
# ...
def close(self):
if self.dct:
self.dct.device.close()
You'll notice I also renamed self.dict to self.dct. Although the former name may technically be allowable because of the self. namespace, dict is actually a built-in class. Under various circumstances, you could wind up dealing with shadowing. In the very least, it's confusing to always have to remind oneself that "this isn't the built-in dict, but an instance variable instead.
(Possible aside: is there a particular reason why you don't want to call start() from the initializer?)
WARNING: This is not a simple case of "copy and paste the answer". I've illustrated a couple of design principles here that you should incorporate into the rest of your code.

Related

Looking for fix for this BrokenPipeError in my python project socket/Threads

first time questioner here!
I´m currently working on a python project that´s supposed to read soil moisture through a sensor on a raspberry pi, which then sends the data to another laptop through a socket connection. That other laptop displays the data in a UI. That UI is also capable of controllig the script flow. My Server starts up just fine, but when the client connects to it(connection itself works), I get the following Error Stack:
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/usr/lib/python3.5/threading.py", line 862, in run
self._target(self._args, **self._kwargs)
File "/home/pi/Py_Scripts/MoistureSensor/Server.py", line 77, in worker_recv
self.JSON_Control = pickle.loads(self.data_recv)
EOFError: Ran out of input
Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.5/threading.py", line 914, in _bootstrap_inner
self.run()
File "/usr/lib/python3.5/threading.py", line 862, in run
self._target(self._args, **self._kwargs)
File "/home/pi/Py_Scripts/MoistureSensor/Server.py", line 70, in worker_send
self.conn.send(self.data_send)
BrokenPipeError: [Errno 32] Broken pipe
My Scripts look as follows:
Client-side:
import sys
from socket import *
from threading import Thread
from time import sleep
import pickle
from PySide6 import QtWidgets, QtGui
class MyClient:
def __init__(self, server_port, buf_size, host):
self.server_port = server_port
self.buf_size = buf_size
self.host = host
self.data_send = None
self.data_recv = None
self.exit = False
self.JSON_Control = {
"measure": False,
"exit": False,
}
self.JSON_Moisture = {
"moisture_level": 0
}
self.socket_connection = socket(AF_INET, SOCK_STREAM)
self.socket_connection.connect((self.host, self.server_port))
print("Connected with Server: %s: " % self.host)
# thread for sending
self.thread_send = Thread(target=self.worker_send)
# thread for receiving
self.thread_recv = Thread(target=self.worker_recv)
# starting Threads
self.thread_send.start()
self.thread_recv.start()
def worker_send(self):
while not self.exit:
self.data_send = pickle.dumps(self.JSON_Control)
self.socket_connection.send(self.data_send)
sleep(0.5)
def worker_recv(self):
while not self.exit:
self.data_recv = self.socket_connection.recv(self.buf_size)
if self.data_recv is not None:
self.JSON_Moisture = pickle.loads(self.data_recv)
class UiDisplay(QtWidgets.QWidget):
def __init__(self):
super().__init__()
self.moisture_label = None
self.moisture_level = None
self.start_button = None
self.refresh_button = None
self.stop_button = None
self.reset_button = None
self.quit_button = None
self.create_widgets()
def create_widgets(self):
# create a label to display the current time
self.moisture_label = QtWidgets.QLabel(self)
self.moisture_label.setFont(QtGui.QFont("Helvetica", 16))
self.moisture_level = client.JSON_Moisture["moisture_level"]
self.moisture_label.setText('Bodenfeuchtigkeit: ' + str(self.moisture_level)[:3] + '%')
# button to start the weight measuring
self.start_button = QtWidgets.QPushButton("Start measuring", self)
self.start_button.clicked.connect(self.measure_moisture)
# button to refresh the Weight label
self.refresh_button = QtWidgets.QPushButton("Refresh", self)
self.refresh_button.clicked.connect(self.refresh)
# button to stop measuring
self.stop_button = QtWidgets.QPushButton("Stop measuring", self)
self.stop_button.clicked.connect(self.stop_measuring)
# button to quit the program
self.quit_button = QtWidgets.QPushButton("Quit", self)
self.quit_button.clicked.connect(self.quit)
# create a layout to hold the widgets
layout = QtWidgets.QVBoxLayout()
layout.addWidget(self.moisture_label)
layout.addWidget(self.start_button)
layout.addWidget(self.refresh_button)
layout.addWidget(self.stop_button)
layout.addWidget(self.reset_button)
layout.addWidget(self.quit_button)
self.setLayout(layout)
def measure_moisture(self):
client.JSON_Control["measure"] = True
def refresh(self):
# get current weight ( niederlag auf ein qm rechnen fehlt noch)
self.moisture_level = round(client.JSON_Moisture["moisture_level"] - 2.7) / (1 - 2.7)
print(self.moisture_level)
# umrechnen von analogem Wert zu Prozentanteil
print(self.moisture_level)
# update the weight label with the current time
self.moisture_label.setText('Bodenfeuchtigkeit: ' + str(self.moisture_level)[:5] + '%')
def stop_measuring(self):
if client.JSON_Control["measure"]:
client.JSON_Control["measure"] = False
else:
pass
def quit(self):
QtWidgets.QApplication.instance().quit()
client.JSON_Control["exit"] = True
sleep(2)
client.exit = True
client.thread_recv.join()
client.thread_send.join()
client.socket_connection.close()
print("Server connection is closed")
print('exiting...')
sleep(1)
sys.exit()
client = MyClient(1957, 1024, "192.168.86.121")
app = QtWidgets.QApplication()
window = UiDisplay()
window.show()
app.exec()
--------------------------------------------------------
The Server-side:
import sys
from socket import *
from threading import Thread
import pickle
from time import sleep
import Adafruit_ADS1x15
adc_channel_0 = 0
class SoilMoistureSensor:
def __init__(self, gain, sps, dry_voltage, saturated_voltage):
self.adc = Adafruit_ADS1x15.ADS1115()
self.raw_data = None
self.moisture_level = None
# self.voltage = None
self.gain = gain
self.sps = sps
self.dry_voltage = dry_voltage
self.saturated_voltage = saturated_voltage
class MyServer:
def __init__(self, echo_port, buf_size):
self.buf_size = buf_size
self.echo_port = echo_port
self.data_send = None
self.data_recv = None
self.exit = False
self.data_json = None
self.moisture_sensor = SoilMoistureSensor(2, 32, 1, 2.7) # gain, sps, saturated_voltage, dry_voltage
self.JSON_Control = {
"measure": False,
"exit": False
}
self.JSON_Moisture = {
"moisture_level": 0,
}
self.socket_connection = socket(AF_INET, SOCK_STREAM)
self.socket_connection.bind(("", self.echo_port))
self.socket_connection.listen(1)
print("Server gestartet")
print("Name des Hosts: ", gethostname())
print("IP des Hosts: ", gethostbyname(gethostname()))
self.conn, (self.remotehost, self.remoteport) = self.socket_connection.accept()
print("Verbunden mit %s %s " % (self.remotehost, self.remoteport))
# thread for sending
self.thread_send = Thread(target=self.worker_send)
# thread for receiving
self.thread_recv = Thread(target=self.worker_recv)
# thread for checking Json Control
self.thread_check_json_control = Thread(target=self.check_json_control)
# starting Threads
self.thread_send.start()
self.thread_recv.start()
self.thread_check_json_control.start()
def worker_send(self):
while not self.exit:
self.data_send = pickle.dumps(self.JSON_Moisture)
self.conn.send(self.data_send)
sleep(0.5)
def worker_recv(self):
while not self.exit:
self.data_recv = self.conn.recv(self.buf_size)
if self.data_recv is not None:
self.JSON_Control = pickle.loads(self.data_recv)
def measure_moisture(self, channel):
channel = adc_channel_0
self.moisture_sensor.raw_data = self.moisture_sensor.adc.read_adc(
channel, self.moisture_sensor.gain, self.moisture_sensor.sps)
self.JSON_Moisture["moisture_level"] = self.moisture_sensor.raw_data
print(self.moisture_sensor.raw_data)
def stop_connection(self):
self.thread_recv.join()
self.thread_send.join()
self.thread_check_json_control.join()
self.socket_connection.close()
print("Server connection is closed")
print('exiting...')
sys.exit()
def check_json_control(self):
while not self.exit:
if self.JSON_Control["measure"]:
self.measure_moisture(0)
if self.JSON_Control["exit"]:
self.stop_connection()
sleep(0.5)
server = MyServer(1957, 1024)
I´d be ever so grateful for help and I´m incredibly sorry if I´ve disregarded any question conventions. Cheers!

How to Update a Label in Pyglet without Invalid Operation Error?

I have a pyglet program that runs a GUI in one thread and receives a message from another thread. It's supposed to update the GUI based on that message. The problem though is whenever I go to update a GUI element, I get an error message like this one:
Traceback (most recent call last):
File --- line 40, in run
pub.sendMessage("update", msg="Banana")
File --- line 77, in updateDisplay
self.label.text = msg
File "---\pyglet\text\__init__.py", line 289, in text
self.document.text = text
File "---\pyglet\text\document.py", line 294, in text
self.insert_text(0, text)
File "---\pyglet\text\document.py", line 425, in insert_text
self.dispatch_event('on_insert_text', start, text)
File "---\pyglet\event.py", line 408, in dispatch_event
if handler(*args):
File "---\pyglet\text\layout.py", line 1045, in on_insert_text
self._init_document()
File "---\pyglet\text\layout.py", line 1034, in _init_document
self._update()
File "---\pyglet\text\layout.py", line 957, in _update
lines = self._get_lines()
File "---\pyglet\text\layout.py", line 933, in _get_lines
glyphs = self._get_glyphs()
...
File "---\pyglet\font\base.py", line 246, in fit
region.blit_into(image, 0, 0, 0)
File "---\pyglet\image\__init__.py", line 1730, in blit_into
self.owner.blit_into(source, x + self.x, y + self.y, z + self.z)
File "---\pyglet\image\__init__.py", line 1622, in blit_into
glBindTexture(self.target, self.id)
File "---\pyglet\gl\lib.py", line 107, in errcheck
raise GLException(msg)
pyglet.gl.lib.GLException: b'invalid operation'
The operative error being pyglet.gl.lib.GLException: b'invalid operation'
I know self.label.text = Y works because it updates the text if I put it in the init() function. However, trying to do any kind of update from the update_display function (see code below) throws this error. I know the function gets called correctly because it successfully prints the message to console, but it breaks on the update element line. I've tried other elements than label and it's the same thing.
I have no idea why it's throwing this error or how to resolve it. Any ideas?
My code is:
import pyglet
from threading import Thread
from random import choice
from time import sleep
from pubsub import pub
RUN = True
class MessageThread(Thread):
def __init__(self):
"""Init Thread Class."""
Thread.__init__(self)
self.start() # start the thread
def run(self):
"""Run Thread."""
array = [0, 1, 2]
while True:
if RUN == False:
print("End runner")
break
value = choice(array)
sleep(1)
if value == 0:
print("event", value, ": Apple", flush=True)
pub.sendMessage("update", msg="Apple")
elif value == 1:
print("event", value, ": Banana", flush=True)
pub.sendMessage("update", msg="Banana")
else:
print("event", value, ": Carrot", flush=True)
pub.sendMessage("update", msg="Carrot")
class MyGUI(pyglet.window.Window):
# Note: With this structure, there is no "self.app", you just use
# self. This structure allows onDraw() to be called.
def __init__(self):
super(MyGUI, self).__init__(width=600,height=650,resizable=True)
self.label = pyglet.text.Label('Waiting...',
font_name='Times New Roman',
font_size=36,
x=self.width/2, y=self.height - 36,
anchor_x='center', anchor_y='center')
# create a pubsub receiver
# update is the topic subscribed to, updateDisplay the callable
pub.subscribe(self.updateDisplay, "update")
MessageThread()
def on_draw(self):
self.clear()
self.label.draw()
def updateDisplay(self, msg):
""" Receives data from thread and updates the display """
print ("Updating Display")
self.label.text = msg
def on_close(self):
""" Override the normal onClose behavior so that we can
kill the MessageThread, too
"""
print("Closing Application")
global RUN
RUN = False
self.close() # Need to include since defining on_close overrides it
if __name__ == "__main__":
window = MyGUI()
pyglet.app.run()

Python signals: ValueError: signal only works in main thread

I have this python code:
from pytchat import LiveChat
import time
import requests
import threading
video_id = None
liveChat = None
def runChat():
global liveChat
liveChat = LiveChat(video_id)
while liveChat.is_alive():
try:
chatdata = liveChat.get()
for c in chatdata.items:
print(f"{c.datetime} [{c.author.channelId}]- {c.message}")
chatdata.tick()
except KeyboardInterrupt:
liveChat.terminate()
break
def checkId():
threading.Timer(1.0, checkId).start()
global video_id
req = requests.get("http://localhost/getId")
if req.status_code == 200:
vidId = req.text
if vidId != "null" and vidId != video_id:
video_id = vidId
print(f"got id: {video_id}")
if liveChat is not None:
liveChat.terminate()
runChat()
def main():
checkId()
if __name__ == '__main__':
main()
That utilizes the pytchat library (https://github.com/taizan-hokuto/pytchat).
As you can see, I want to dynamically change the videoId that the chat is bundled to, but with the code above this is the result:
root#vps:~# python3 liveChat.py
got id: a10TAdVZmOq # First id, the library works, we can capture chat messages.
got id: NMre6IAPoLI # After second id appears, there is this exception:
Exception in thread Thread-52:
Traceback (most recent call last):
File "/usr/local/lib/python3.6/threading.py", line 916, in _bootstrap_inner
self.run()
File "/usr/local/lib/python3.6/threading.py", line 1182, in run
self.function(*self.args, **self.kwargs)
File "liveChat.py", line 36, in checkId
runChat()
File "liveChat.py", line 11, in runChat
liveChat = LiveChat(video_id)
File "/usr/local/lib/python3.6/site-packages/pytchat/core_multithread/livechat.py", line 110, in __init__
signal.signal(signal.SIGINT, lambda a, b: self.terminate())
File "/usr/local/lib/python3.6/signal.py", line 47, in signal
handler = _signal.signal(_enum_to_int(signalnum), _enum_to_int(handler))
ValueError: signal only works in main thread
How can this be solved since signals only work in main thread?
Adding the parameter interruptable=False to the LiveChat object solved the issue.
def runChat():
global liveChat
liveChat = LiveChat(video_id, interruptable=False) # <---THIS
while liveChat.is_alive():
# ....
https://github.com/taizan-hokuto/pytchat/issues/8

emulate file-like behavior in python

I'm writing a script, where I have to dump some columns of tables from an SQL database into a file, and transfer it via FTP.
Because dumps can get really big, my Idea was to write a FakeFile which querys row by row from a cursor in its readline method and pass it to ftplib.FTP.storlines.
This is what I have so far:
import ftplib
import MySQLdb
def MySQLFakeFile(object):
'''
Simulates a read-only file, which dumps rows on demand.
Use this, to pass it to the FTP protocol to make the dump more efficient,
without the need to dump it somewhere and copy it over the net afterwords
'''
def __init__(self, cursor, delimeter, table_name, query):
self.cursor = cursor
self.delimeter = delimeter
self.table_name = table_name
#query is something along select ... FROM %s
self.cursor.execute(query, table_name)
self._has_written_index = False
#file attrs
self.closed = False
self.name = table_name + ".csv"
self.encoding = "utf-8"
self.mode = "r"
def close(self):
self.cursor.close()
self.closed = True
def flush(self):
'''No-OP'''
pass
def read(self, size):
pass
def readline(self, size):
if not self._has_written_index:
ret = []
for desc in self.cursor.description:
ret.append(desc[0])
self._has_written_index = True
else:
ret = self.cursor.fetchone()
if not ret:
return None
s = ""
for col in ret:
s += str(col) + self.delimeter
return s + "\n"
def readlines(self, size):
ret = []
line = self.readline()
while line:
ret.append(line)
line = self.readline()
def write(self, string):
raise Exception("cannot write to a MySQLFakeFile")
def writelines(self, lines)
raise Exception("cannot write to a MySQLFakeFile")
db = MySQLdb("host", "user", "pass", "db")
ftp = ftplib.FTP("host", "user", "pass")
fakeFile = MySQLFakeFile(db.cursor(), ";", "tableName", "SELECT * FROM %s")
ftp.storlines("STOR tableName.csv", fakeFile)
gives me
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/ftplib.py", line 496, in storlines
if len(buf) > self.maxline:
TypeError: object of type 'NoneType' has no len()
What am I doing wrong, and whats the NoneType here?
Your readline returns None instead of empty string "" when reached end-of-rows.
Your readlines returns nothing.
def readlines(self, size):
ret = []
while True:
line = self.readline()
if not line:
break
ret.append(line)
return ret

TypeError: cannot concatenate 'str'

I got this error TypeError: cannot concatenate 'str' and 'builtin_function_or_method' objects when i tried to change directory in the ftp.
ftp.py
from ftplib import FTP
ftp = FTP()
class FTPClient():
connection_id = None
login_ok = False
message_array = []
def __init__(self):
pass
def log_message(self, message, clear=True):
if clear:
self.message_array = message
def get_message(self):
return self.message_array
def connect(self, server, ftp_user, ftp_password, is_passive = False):
self.connection_id = ftp.connect(server)
login_result = ftp.login(user=ftp_user, passwd=ftp_password)
ftp.set_pasv(is_passive)
if not self.connection_id or not login_result:
self.log_message("FTP Connection has Failed")
self.log_message("Attempted to connect to {0} for {1}".format(server, ftp_user))
return False
else:
self.log_message("Connected to {0} for {1}".format(server, ftp_user))
self.login_ok = True
return True
def make_dir(self, directory):
if ftp.mkd(directory):
self.log_message("Directory {0} created successfully".format(directory))
return True
else:
self.log_message("Failed creating directory")
return False
def change_directory(self, directory):
if ftp.cwd(directory):
self.log_message("Current Directory is now {0}".format(ftp.pwd))
else:
self.log_message("Can't change Directory")
def upload_file(self, file_from, file_to):
if file_from.endswith(('.csv', '.txt')):
with open(file_from, 'r') as f:
self.connection_id.storelines("Uploaded from {0} to {1}".format(file_from, file_to), f)
else:
with open(file_from, 'rb') as f:
self.connection_id.storebinary('Uploaded from {0} to {1}'.format(file_from, file_to), f)
ftp_obj = FTPClient()
FTP_HOST = "yyy"
FTP_USER = "xxx"
FTP_PASS = "zzz"
ftp_obj.connect(FTP_HOST, FTP_USER, FTP_PASS)
print(ftp_obj.get_message())
FILE_FROM = "config.txt"
FILE_TO = ftp_obj.change_directory(dir)
ftp_obj.upload_file(FILE_FROM, FILE_TO)
print(ftp_obj.get_message())
Full traceback:
Connected to yyy for xxx
Traceback (most recent call last):
File "C:/Users/Ajay/PycharmProjects/database/test.py", line 67, in <module>
FILE_TO = ftp_obj.change_directory(dir)
File "C:/Users/Ajay/PycharmProjects/database/test.py", line 44, in change_directory
if ftp.cwd(directory):
File "C:\Python27\lib\ftplib.py", line 552, in cwd
cmd = 'CWD ' + dirname
TypeError: cannot concatenate 'str' and 'builtin_function_or_method' objects
Whats happening there ? and why this error ?
Error is here:
FILE_TO = ftp_obj.change_directory(dir)
you have not declared dir var, builtin function dir passed instead.

Categories

Resources