I'm trying to develop some kind of terminal user interface in python3
with threading and ncurse and some weird characters appear.
Based on the answer in this post:
Threading with Python Curses giving me weird characters?
which is exactly my problem, i tried to implement locking the maj() function (and also tested with rlock) in my code .
But it seams the lock does not block other thread .
Is my lock misplaced ?? or am i hitting a technical limit ?
here after is an example my code :
import threading
from time import sleep
import curses
import logging
from curses.textpad import Textbox, rectangle
from datetime import datetime
class GenericTUI(threading.Thread):
def __init__(self,textmode=False, messageBoxSize=10, logger=logging.getLogger()):
threading.Thread.__init__(self)
self.keyPressedList = list()
self.alive = True
self.myStdscr = None
self.title = ""
self.messageList = list()
self.messageBoxSize = messageBoxSize
self.subTitle = ""
self.priceInfo = ""
self.progInfo = ""
self.textMode = textmode
self.logger = logger
self.lock = threading.Lock()
def run(self):
if self.textMode :
with open('/tmp/genericTUI.command','w+') as f:
# command file in text mode
pass
while self.alive :
print("Program :"+ self.title)
print("sub"+self.subTitle)
print("Prices : "+self.priceInfo)
print("ProgInfos :"+self.progInfo)
for m in self.messageList :
print(m)
with open('/tmp/genericTUI.command','r+') as f:
c = f.read(1)
if c:
self.keyPressedList.append(c)
f.truncate(0)
sleep(5)
else :
curses.wrapper(self.main)
def maj(self):
'''
mise a jour de l ecran
au sujet du thread lock :
https://stackoverflow.com/questions/46773577/threading-with-python-curses-giving-me-weird-characters
'''
# determine la taille de l ecran
max_y, max_x = self.myStdscr.getmaxyx()
# reecriture
with self.lock :
try :
self.myStdscr.clear()
for x in range(max_x):
self.myStdscr.addch(0,x,curses.ACS_HLINE)
self.myStdscr.addstr(1, 2, "Program :"+ self.title, curses.color_pair(1) )
self.myStdscr.addstr(2, 2, self.subTitle)
for x in range(max_x):
self.myStdscr.addch(3,x,curses.ACS_HLINE)
self.myStdscr.addstr(4, 2, "Prices : "+self.priceInfo, curses.color_pair(2))
for x in range(max_x):
self.myStdscr.addch(5,x,curses.ACS_HLINE)
self.myStdscr.addstr(6, 2, "ProgInfos :"+self.progInfo, curses.color_pair(5))
for x in range(max_x):
self.myStdscr.addch(7,x,curses.ACS_HLINE)
indent =0
for m in self.messageList :
self.myStdscr.addstr(8+indent, 3,m)
indent+=1
for y in range(max_y):
self.myStdscr.addch(y,0,curses.ACS_VLINE)
self.myStdscr.refresh()
except Exception as e:
self.logger.error(repr(e))
self.myStdscr.clear()
def main(self,stdscr):
# color definition
if curses.has_colors():
curses.start_color()
curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_RED)
curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_YELLOW)
curses.init_pair(4, curses.COLOR_BLACK, curses.COLOR_BLUE)
curses.init_pair(5, curses.COLOR_BLACK, curses.COLOR_GREEN)
## NE SURTOUT PAS METTRE keypad(false) GENERE DES CARACTERES AU HASARD .. DANGEREUX
self.myStdscr = stdscr
self.myStdscr.nodelay(True)
self.myStdscr.keypad(True)
self.myStdscr.box()
counter = 0
while self.alive:
try :
key = self.myStdscr.getkey()
self.keyPressedList.append(key)
except Exception as e:
## le nodelay rend l interface reactive mais ,le getkey genere un noinput error
## si pas de touche pressée d ou le pass
pass
sleep(0.1)
counter +=1
def getKeyPressed(self):
if self.keyPressedList :
return self.keyPressedList.pop()
else :
return None
def stop(self):
self.alive = False
def updatePriceInfo(self,priceDict,maj=False):
result = " ".join(str(key) +":"+ str(value)+"|" for key, value in priceDict.items())
self.priceInfo = result
if maj :
self.maj()
def updateTitle(self,title, maj=False):
self.title = str(title)
if maj :
self.maj()
def updateSubTitle(self,subtitleDict, maj=False):
result = " ".join(str(key) +":"+ str(value)+"|" for key, value in subtitleDict.items())
self.subTitle = str(result)
if maj :
self.maj()
def updateProgInfo(self,messDict, maj=False):
result = " ".join(str(key) +":"+ str(value)+"|" for key, value in messDict.items())
self.progInfo = result
if maj :
self.maj()
def addMessage(self,mess, maj=False):
self.messageList.append(repr(mess))
if len(self.messageList) > self.messageBoxSize : self.messageList.pop(0)
if maj :
self.maj()
def getValue(self, mess="Enter Value: (hit Ctrl-G to send)"):
self.myStdscr.addstr(0, 0, mess)
editwin = curses.newwin(1,7, 2,1)
rectangle(self.myStdscr, 1,0, 1+1+1, 1+7+1)
self.myStdscr.refresh()
box = Textbox(editwin)
box.stripspaces = True
# Let the user edit until Ctrl-G is struck.
box.edit()
# Get resulting contents
return(box.gather().strip())
if __name__ == "__main__":
## the main is used for some test when the lib is called directly
testGUI = GenericTUI()
alive = True
testGUI.logger.addHandler(logging.StreamHandler())
testGUI.logger.setLevel(logging.DEBUG)
testGUI.start()
while alive :
testGUI.updateTitle('time %s'%str(datetime.now() ))
k = testGUI.getKeyPressed()
if k is not None:
if k=='Q' :
alive = False
elif k=='M' :
mess = testGUI.getValue()
testGUI.addMessage(mess,maj=True)
else :
testGUI.addMessage('unknown key %s'%k , maj=True)
sleep(0.1)
testGUI.stop()
as you can see there is a with self.lock statement in the maj()function o the class, but
in my log i still get a lot of errors like :
alphanumeric key ? pressed
unknown key press : ?
alphanumeric key [ pressed
unknown key press : [
alphanumeric key pressed
unknown key press :
alphanumeric key ? pressed
where should i place my lock to avoid that ??
I answer my own question, but I think it will be hepfull for others :
The trick is in the ncurses wrapper which have is own thread . So If i want the lock to work I have to put it in the main loop .
Below is the code modified :
import threading
from time import sleep
import curses
import logging
from curses.textpad import Textbox, rectangle
from datetime import datetime
import re
class GenericTUI(threading.Thread):
def __init__(self,textmode=False, messageBoxSize=10, logger=logging.getLogger()):
threading.Thread.__init__(self)
self.keyPressedList = list()
self.alive = True
self.myStdscr = None
self.title = ""
self.messageList = list()
self.messageBoxSize = messageBoxSize
self.subTitle = ""
self.priceInfo = ""
self.progInfo = ""
self.textMode = textmode
self.logger = logger
self.lock = threading.Lock()
self.refreshFlag = True
def run(self):
if self.textMode :
with open('/tmp/genericTUI.command','w+') as f:
# command file in text mode
pass
while self.alive :
print("Program :"+ self.title)
print("sub"+self.subTitle)
print("Prices : "+self.priceInfo)
print("ProgInfos :"+self.progInfo)
for m in self.messageList :
print(m)
with open('/tmp/genericTUI.command','r+') as f:
c = f.read(1)
if c:
self.keyPressedList.append(c)
f.truncate(0)
sleep(5)
else :
curses.wrapper(self.main)
def main(self,stdscr):
# color definition
if curses.has_colors():
curses.start_color()
curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLUE)
curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_RED)
curses.init_pair(3, curses.COLOR_WHITE, curses.COLOR_YELLOW)
curses.init_pair(4, curses.COLOR_BLACK, curses.COLOR_BLUE)
curses.init_pair(5, curses.COLOR_BLACK, curses.COLOR_GREEN)
## NE SURTOUT PAS METTRE keypad(false) GENERE DES CARACTERES AU HASARD .. DANGEREUX
self.myStdscr = stdscr
self.myStdscr.nodelay(True)
self.myStdscr.keypad(True)
self.myStdscr.box()
counter = 0
while self.alive:
try :
key = self.myStdscr.getkey()
#workaround to avoid multi thread escape character
if re.match('[A-Z_\+\-\*/]', key) :
self.keyPressedList.append(key)
except Exception as e:
## le nodelay rend l interface reactive mais ,le getkey genere un noinput error
## si pas de touche pressée d ou le pass
pass
'''
screen update in the mail loop
to be able to thread lock :
https://stackoverflow.com/questions/46773577/threading-with-python-curses-giving-me-weird-characters
'''
# determine la taille de l ecran
max_y, max_x = self.myStdscr.getmaxyx()
# reecriture
if self.refreshFlag:
try :
with self.lock :
self.myStdscr.clear()
for x in range(max_x):
self.myStdscr.addch(0,x,curses.ACS_HLINE)
self.myStdscr.addstr(1, 2, "Program :"+ self.title, curses.color_pair(1) )
self.myStdscr.addstr(2, 2, self.subTitle)
for x in range(max_x):
self.myStdscr.addch(3,x,curses.ACS_HLINE)
self.myStdscr.addstr(4, 2, "Prices : "+self.priceInfo, curses.color_pair(2))
for x in range(max_x):
self.myStdscr.addch(5,x,curses.ACS_HLINE)
self.myStdscr.addstr(6, 2, "ProgInfos :"+self.progInfo, curses.color_pair(5))
for x in range(max_x):
self.myStdscr.addch(7,x,curses.ACS_HLINE)
indent =0
for m in self.messageList :
self.myStdscr.addstr(8+indent, 3,m)
indent+=1
for y in range(max_y):
self.myStdscr.addch(y,0,curses.ACS_VLINE)
self.myStdscr.refresh()
except Exception as e:
self.logger.error(repr(e))
self.myStdscr.clear()
finally:
self.refreshFlag = False
sleep(0.1)
counter +=1
def getKeyPressed(self):
if self.keyPressedList :
return self.keyPressedList.pop()
else :
return None
def stop(self):
self.alive = False
def updatePriceInfo(self,priceDict,maj=False):
result = " ".join(str(key) +":"+ str(value)+"|" for key, value in priceDict.items())
self.priceInfo = result
self.refreshFlag = maj
def updateTitle(self,title, maj=False):
self.title = str(title)
self.refreshFlag = maj
def updateSubTitle(self,subtitleDict, maj=False):
result = " ".join(str(key) +":"+ str(value)+"|" for key, value in subtitleDict.items())
self.subTitle = str(result)
self.refreshFlag = maj
def updateProgInfo(self,messDict, maj=False):
result = " ".join(str(key) +":"+ str(value)+"|" for key, value in messDict.items())
self.progInfo = result
self.refreshFlag = maj
def addMessage(self,mess, maj=False):
self.messageList.append(repr(mess))
if len(self.messageList) > self.messageBoxSize : self.messageList.pop(0)
self.refreshFlag = maj
def getValue(self, mess="Enter Value: (hit Ctrl-G to send)"):
with self.lock :
self.myStdscr.addstr(0, 0, mess)
editwin = curses.newwin(1,7, 2,1)
rectangle(self.myStdscr, 1,0, 1+1+1, 1+7+1)
box = Textbox(editwin)
box.stripspaces = True
self.myStdscr.refresh()
# Let the user edit until Ctrl-G is struck.
box.edit()
# Get resulting contents
return(box.gather().strip())
if __name__ == "__main__":
## the main is used for some test when the lib is called directly
testGUI = GenericTUI()
alive = True
testGUI.logger.addHandler(logging.StreamHandler())
testGUI.logger.setLevel(logging.DEBUG)
testGUI.start()
while alive :
testGUI.updateTitle('time %s'%str(datetime.now() ))
k = testGUI.getKeyPressed()
if k is not None:
if k=='Q' :
alive = False
elif k=='M' :
mess = testGUI.getValue()
testGUI.addMessage(mess,maj=True)
else :
testGUI.addMessage('unknown key %s'%k , maj=True)
sleep(0.1)
testGUI.stop()
```
you may also notice there is another lock in the getvalue function to avoid the main thread to erase the textbox .
Hope this help others.
Related
run python.py and show this error
import boto3, datetime, sys, getopt, re
from operator import itemgetter
from table_logger import TableLogger
class buck:
TARIFAWS = 0.023 # 0,023 USD por GB (Primeiros 50 TB por mês)
counter = 0
def __init__(self, s3bucket):
buck.counter = buck.counter + 1
self.name = s3bucket.name
self.creationdate = s3bucket.creation_date
self.size = self.metricCloudwatch(s3bucket,"BucketSizeBytes", "StandardStorage")
self.nbreObj = self.metricCloudwatch(s3bucket,"NumberOfObjects", "AllStorageTypes")
try:
boto3.client('s3').get_bucket_encryption(Bucket=s3bucket.name)
self.number = True
except:
self.number = False
self.region = (boto3.client('s3').get_bucket_location(Bucket=s3bucket.name))['LocationConstraint']
self.cout = round(self.size / 1024**3 * self.TARIFAWS,2)
try:
boto3.client('s3').get_bucket_replication(Bucket=s3bucket.name)
self.replica = True
except:
self.replica = False
def collObjInfo(self):
s3obj = (boto3.client('s3')).list_objects_v2(Bucket=self.name)
self.lastupdate = None
self.typeStorage = None
if s3obj['KeyCount'] != 0:
self.lastupdate = s3obj['Contents'][0]['LastModified']
self.typeStorage = s3obj['Contents'][0]['StorageClass']
collObjInfo(self)
self.public = False
def __str__(self):
return str(self.__class__) + ": " + str(self.__dict__)
def __getitem__(self, key):
if key == 'region':
return self.region
if key == 'typeStorage':
return self.typeStorage
def getSize(self, human=False):
if human:
return humanReadable(self.size)
else:
return self.size
def metricCloudwatch(self, bucket, nameMetric, storage):
cloudwatch = boto3.client('cloudwatch')
now = datetime.datetime.now()
try:
cloudwatch_size = cloudwatch.get_metric_statistics(
Namespace='AWS/S3',
MetricName=nameMetric,
Dimensions=[
{'Name': 'BucketName', 'Value': bucket.name},
{'Name': 'StorageType', 'Value': storage}
],
Statistics=['Maximum'],
Period=86400,
StartTime=(now - datetime.timedelta(days=1)).isoformat(),
EndTime=now.isoformat()
)
if cloudwatch_size["Datapoints"]:
return cloudwatch_size["Datapoints"][0]['Maximum']
else:
return 0
except:
return 0
def humanReadable(num, suffix='B'):
for unit in ['','K','M','G','T','P']:
if abs(num) < 1024.0:
return "%3.1f%s%s" % (num, unit, suffix)
num /= 1024.0
return "%.1f%s%s" % (num, 'Yi', suffix)
def help():
print("Uso : bucket.py [OPTIONS]")
print("Exibe informações sobre buckets AWS S3, por padrão")
print("Argumentos : \n\
--help \t\t\t ajuda\n\
--crypted-only \t\t mostra apenas buckets criptografados\n\
-c, --csv \t\t mostra o resultado em CSV\n\
-s, --sorted \t\t agrupar resultados por região e grupo de armazenamento\n\
-h, --human-readable \t exibem tamanhos de 1024\n\
-f, --filter=filter \t filtra a lista de buckets com base na expressão regular FILTER")
def main():
csv=False
human = False
group = False
filterCrpt = False
filter = None
try:
opts, args = getopt.getopt(sys.argv[1:], "shcf:", ["sorted", "help", "csv", "human-readable", "crypted-only", "filter:"])
except:
print("Comando incorreto, aqui está a ajuda: ")
help()
sys.exit(2)
for opts, args in opts:
if opts == "--help":
help()
sys.exit()
elif opts == "--crypted-only":
filterCrpt = True
elif opts in ("-c", "--csv"):
csv = True
elif opts in ("-s", "--sorted"):
group = True
elif opts in ("-h", "--human-readable"):
human = True
elif opts in ("-f", "--filter"):
if len(args):
filter = args
else:
help()
sys.exit(2)
s3 = boto3.resource('s3')
bucks = []
listeS3Bucks = s3.buckets.all()
for bucket in listeS3Bucks:
try:
if filter:
re.match(filter,"Test chain")
except:
print("Regular expression error")
sys.exit(2)
if (filter and re.match(filter,bucket.name)) or not filter:
try:
bucks.append(buck(bucket))
except:
print("Erro ao conectar ao AWS, verifique suas configurações")
print("Para obter mais informações: https://docs.aws.amazon.com/cli/latest/userguide/cli-config-files.html")
sys.exit(2)
if group:
bucks = sorted(bucks, key=itemgetter('region'))
bucks = sorted(bucks, key=itemgetter('typeStorage'))
tbl = TableLogger(columns='name,creation date,last update,size,number of objects,number,storage,public,region,cost,replica',
csv=csv, border=False)
for cBuck in bucks:
if (filterCrpt and cBuck.number) or not filterCrpt:
tbl(cBuck.name, cBuck.creationdate, cBuck.lastupdate, cBuck.getSize(human), str(cBuck.nbreObj),
cBuck.number,cBuck.typeStorage, cBuck.public, cBuck.region, "$"+str(cBuck.cout),cBuck.replica)
if __name__ == "__main__":
main()
when trying to run the script in python, it gives this error:
TypeError: unsupported format string passed to NoneType.format
can someone help me? is a script that pulls information from aws s3 bucket.
Bucket is a python script to extract statistics from S3 buckets. It is based on Cloudwatch monitoring metrics.
Help plis
File "C:\Python39\lib\site-packages\table_logger\table_logger.py", line 203, in __call__
line = self.format_row(*row_cells)
File "C:\Python39\lib\site-packages\table_logger\table_logger.py", line 207, in format_row
vals = [self.format_column(value, col) for col, value in enumerate(args)]
File "C:\Python39\lib\site-packages\table_logger\table_logger.py", line 207, in <listcomp>
vals = [self.format_column(value, col) for col, value in enumerate(args)]
File "C:\Python39\lib\site-packages\table_logger\table_logger.py", line 212, in format_column
return self.formatters[col](value)
File "C:\Python39\lib\site-packages\table_logger\fmt.py", line 40, in __call__
fmt = self.fmt(value)
TypeError: unsupported format string passed to NoneType.__format__
I have implemented an iterable class in python3.8 following this post implementing the weakref() function in order to be able to delete elements of the class, as explained in the post's accepted answer.
The problem is that if I populate the iterable class inside a function I am no longer able to iterate over its elements:
#! /usr/bin/env python3.8
import sys
import weakref
# from memory_profiler import profile
# IN = "/home/enrico/Dropbox/NY/asilo_variant/inputs/merged.idter_M.norm.PASS.filtered.head1k.VEPoutput.vcf"
a = [ "a", "b", "c", "d" ]
class VEPh_iterator(type):
def __iter__(self):
return self.classiter()
class VEPh:
'''
this stores VEP header and relative column numbers and chars
'''
__metaclass__ = VEPh_iterator
by_id = {}
def __init__(self, id, column_number):
self.id = id
# self.by_id[id] = self
self.by_id[id] = weakref.ref(self)
self.column_number = column_number
#classmethod
def classiter(cls):
# return iter(cls.by_id.values())
return (i for i in (i() for i in cls.by_id.values()) if i is not None)
def readVCF( ):
name_dict = {}
for i,s in enumerate(a) :
name_dict.update({ i : s })
name_dict[i] = VEPh( s, i )
if __name__ == "__main__" :
readVCF( )
for v in VEPh.classiter():
print( " - " + v.id + " : " + str(v.column_number) )
calling it has an empty OUT:
python3.8 /home/enrico/Dropbox/NY/asilo_variant/asilo_variant.stackoverflow.py
### NO STDOUT
if modified removing weakref() it works:
#! /usr/bin/env python3.8
import sys
import weakref
# from memory_profiler import profile
# IN = "/home/enrico/Dropbox/NY/asilo_variant/inputs/merged.idter_M.norm.PASS.filtered.head1k.VEPoutput.vcf"
a = [ "a", "b", "c", "d" ]
class VEPh_iterator(type):
def __iter__(self):
return self.classiter()
class VEPh:
'''
this stores VEP header and relative column numbers and chars
'''
__metaclass__ = VEPh_iterator
by_id = {}
def __init__(self, id, column_number):
self.id = id
self.by_id[id] = self
# self.by_id[id] = weakref.ref(self)
self.column_number = column_number
#classmethod
def classiter(cls):
return iter(cls.by_id.values())
# return (i for i in (i() for i in cls.by_id.values()) if i is not None)
def readVCF( ):
name_dict = {}
for i,s in enumerate(a) :
name_dict.update({ i : s })
name_dict[i] = VEPh( s, i )
if __name__ == "__main__" :
readVCF( )
for v in VEPh.classiter():
print( " - " + v.id + " : " + str(v.column_number) )
calling it works:
python3.8 /home/enrico/Dropbox/NY/asilo_variant/asilo_variant.stackoverflow.py
- a : 0
- b : 1
- c : 2
- d : 3
I guess the problem is that weakref() is somehow lost between functions, but how can I make it callable by outer functions?
I need to do a limete of type 4 characters, with numbers it goes and does not return error, but with letters it returns that error as it is in the title. I need to limit from "0 to 9" and "A to D".
In the limiteUsuario() method, everything is ok.
from tkinter import *
import tkinter as tk
class loginUser:
def __init__(self, window, master=None):
self.wind = window
self.wind.title("System F2T")
#Definicoes de fonte p/ o layout de login
self.fonteTitulo = ("Arial","10","bold")
self.fontePadrao = ("Arial", "10")
self.var = StringVar() #create the var first before you assign them
self.var2 = StringVar()
#Labels e campos de texto do sistema de login
self.userLabel = Label(text="Digite seu usuário:", font=self.fontePadrao,bg="#000",fg="#FFF").place(x=27,y=60)
self.user = Entry(textvariable=self.var, font=self.fontePadrao,bg="#FFF",fg="#000")
self.user.place(x=140,y=60,width=110)
self.senhaLabel = Label(text="Digite sua senha:", font=self.fontePadrao,bg="#000",fg="#FFF").place(x=29,y=90)
self.senha = Entry(textvariable=self.var2, font=self.fontePadrao,bg="#FFF",fg="#000")
self.senha.place(x=140,y=90,width=110)
self.max_user = 1
self.var.trace("w", self.limiteUsuario)
self.max_senha = 4
self.var2.trace("w", self.limiteSenha)
def limiteUsuario(self,*args):
u = self.var.get()
if len(u) == 1 and not 65<=ord(u)<=68 and not 48<=ord(u)<=57: # you can also use *if not u in "ABCD"*
self.var.set("")
elif len(u) > 1:
if not 65<=ord(u[-1])<=68: # retirar ultimo caracter caso nao seja digito
self.var.set(u[:-1])
else: # aproveitar apenas os primeiros 5 chars
self.var.set(u[:self.max_user])
def limiteSenha(self,*args):
text = self.var2.get()
text = ''.join(char for char in text if char in 'ABCD')
if len(text) == 4 and not 65<=ord(text)<=68 and not 48<=ord(text)<=57: # you can also use *if not u in "ABCD"*
self.var2.set("")
elif len(text) > 4:
if not 65<=ord(text[-1])<=68: # retirar ultimo caracter caso nao seja digito
self.var2.set(text[:-1])
else: # aproveitar apenas os primeiros 5 chars
self.var2.set(text[:self.max_senha])
print(self.var2.set(text))
if __name__ == "__main__":
root = Tk()
root['bg'] = "#000"
loginUser(root)
#Tamanho da janela
root.geometry("330x200")
root.mainloop()
ord() can convert only single char - like ord("a") - but you have string with many chars - like ord("BXA7D")
You can use for loop to work with every char separatelly
text = "BXA7D" # text = self.var2.get()
text = ''.join(char for char in text if char in 'ABCD')
print(text) # self.var2.set(text)
# BAD
or longer
text = "BXA7D" # text = self.var2.get()
result = []
for char in text:
if char in 'ABCD':
result.append(char)
text = ''.join(result)
print(text) # self.var2.set(text)
# BAD
EDIT: I don't know what result exactly you want. Delete all string if there is ABCD0123456789 or remove only chars ABCD0123456789
This remove all string if there is char ABCD0123456789 or cut to 5 chars.
def limiteSenha(self,*args):
s = self.var2.get()
if len(s) > 5:
for char in s:
if char not in 'ABCD0123456789':
s = ""
break # exit for-loop because there is no need to check rest
self.var2.set(s[:self.max_senha])
elif len(s) == 5:
if not 65<=ord(s[-1])<=68: # retirar ultimo caracter caso nao seja digito
self.var2.set(s[:-1])
else: # aproveitar apenas os primeiros 5 chars
self.var2.set(s[:self.max_senha])
I am trying to create the GUI code for my connect four boardgame but error's keep on coming up that I don't know how to correct. Can anyone help? The error:
TypeError: init() missing 1 required positional argument: 'buttns_list'
Code:
def __init__(self):
self.mw = tkinter.Tk()
self.mw.title = ("Connect Four")
self.rows = 6
self.cols = 7
self.buttons_2d_list = []
for i in range (self.rows):
self.rows = ['']*self.cols
self.buttons_2d_list.append(self.rows)
self.gboard = ConnectFourBoard()
p1 = HumanPlayer("X")
p2 = ComputerPlayer("O", self.buttns_list)
self.players_1st = (p1, p2)
self.currnt_player_index = 0
self.winner = False
def clicked_btn(self, x, y):
p = self.players_1st[self.currnt_player_index]
button = self.buttons_2d_list[x][y]
if button["text"] == "":
button["text"] = p.get_player_symbol()
self.gboard.MakeMove(x, y, p.get_player_symbol())
winner = self.gboard.CheckForWin()
is_full = self.gboard.FullBoard()
if winner == True:
win_message = ("Player %s is the winner!" %p.get_player_symbol())
messagebox.showinfo("Winner Info", win_messge)
self.mw.destroy()
exit()
elif is_full == True:
messagebox.showinfo("Winner Info", "The game is a draw")
self.mw.destroy()
exit()
else:
pass
if self.currnt_player_index == 1:
self.currnt_player_index = 0
else:
self.currnt_player_index += 1
p = self.players_1st[self.currnt_player_index]
p.play()
import random
class ComputerPlayer(Player):
def __init__(self, letter, buttns_list):
Player.__init__(self, letter)
self.buttons_2d_list = buttns_list
def play(self):
pass
It's not clear to me from the rest of the code exactly what you should be passing here, but your init calls for a letter, which you do have, and a buttns_list, which you don't:
def __init__(self, letter, buttns_list):
So the error comes from this line:
p2 = ComputerPlayer("O")
Either:
1) Pass in a buttns_list if your ComputerPlayer class needs it
p2 = ComputerPlayer("O", self.buttons_2d_list)` # in GameGUI init
2) Get rid of it if this was added by mistake:
class ComputerPlayer(Player):
def __init__(self, letter):
Player.__init__(self, letter)
I have been fighting with a threaded send of an string image over python sockets for a while now and have had no luck on this issue.
code for the client side is:
import socket
from PIL import ImageGrab #windows only screenshot
from threading import Thread
import win32api, win32con
import re
import win32com.client
import getpass
import time
import select
shell = win32com.client.Dispatch("WScript.Shell")
host = raw_input("SERVER:")
dm = win32api.EnumDisplaySettings(None, 0)
dm.PelsHeight = 800
dm.PelsWidth = 600
win32api.ChangeDisplaySettings(dm, 0)
port = 9000
def picture():
while 1:
image = ImageGrab.grab().resize((800,600)) #send screen as string
data = image.tostring()
sendme = (data)
try:
s.sendall(sendme)
print ("sent")
except socket.error as e:
print e
except Exception as e:
print e
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((host, port))
pict = Thread(target=picture)
pict.start()
while 1:
socket_list = [s]
# Get the list sockets which are readable
read_sockets, write_sockets, error_sockets = select.select(socket_list , [], [])
for sock in read_sockets:
if sock == s:
data = sock.recv(1024)
print data
if "LEFTC" in data:
data = data.replace("LEFTC","")
x = re.findall(r'X(.*?)Y',data)
y = re.findall(r'Y(.*?)EOC',data)
x = str(x)
y = str(y)
#REPLACE CODE TO BE REWRITTEN
x = x.replace("[","").replace("]","").replace("'","").replace(" ","")
y = y.replace("[","").replace("]","").replace("'","").replace(" ","")
print(str(x) + ' X\n')
print(str(y) + ' Y\n')
try:
win32api.SetCursorPos((int(x),int(y))) #click time
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTDOWN,int(x),int(y),0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_LEFTUP,int(x),int(y),0,0)
except Exception as e:
print e
elif "RIGHTC" in data:
data = data.replace("RIGHTC","")
x = re.findall(r'X(.*?)Y',data)
y = re.findall(r'Y(.*?)EOC',data)
x = str(x)
y = str(y)
#REPLACE FUNCTION MAREKD FOR REWRITE
x = x.replace("[","").replace("]","").replace("'","").replace(" ","")
y = y.replace("[","").replace("]","").replace("'","").replace(" ","")
print(str(x) + ' X\n')
print(str(y) + ' Y\n')
try: #click
win32api.SetCursorPos((int(x),int(y)))
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTDOWN,int(x),int(y),0,0)
win32api.mouse_event(win32con.MOUSEEVENTF_RIGHTUP,int(x),int(y),0,0)
except Exception as e:
print e
else:
#This does not work correctly: only BACKSPACE and the else are working.
if "CAPS" in data:
shell.SendKeys('{CAPSLOCK}')
elif "CAPSOFF" in data:
shell.SendKeys('{CAPSLOCK}')
elif "BACKSPACE" in data:
shell.SendKeys('{BACKSPACE}')
elif "SHIFT" in data:
shell.SendKeys('+' + data)
else:
shell.SendKeys(data)
time.sleep(0.1)
server code is:
import socket
import pygame
from pygame.locals import *
from threading import Thread
x = y = 0
host = ""
#port defined here
port = 9000
#This list is used to make the library more pythonic and compact. This also leads to less source code.
keylist = [pygame.K_a,pygame.K_b,pygame.K_c,pygame.K_d,pygame.K_e,pygame.K_f,pygame.K_g,pygame.K_h,pygame.K_i,pygame.K_j,pygame.K_k,pygame.K_l,pygame.K_m,pygame.K_n,pygame.K_o,pygame.K_p,pygame.K_q,pygame.K_r,pygame.K_s,pygame.K_t,pygame.K_u,pygame.K_v,pygame.K_w,pygame.K_x,pygame.K_y,pygame.K_z]
key = ['a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z','1','2','3','4','5','6','7','8','9','0']
i/o function
def ioinput(sock):
while 1:
evt = pygame.event.poll() #has to be in the same while loop as the evt called or wont work.
if evt.type == pygame.MOUSEBUTTONDOWN and evt.button == 1: # one for left
x, y = evt.pos
command = ("LEFTC" + " " + "X" + str(x) + "Y" + str(y) + "EOC")
sock.sendall(command)
elif evt.type == pygame.MOUSEBUTTONDOWN and evt.button == 3: # 3 for right 2 is middle which support comes for later.
x, y = evt.pos
command = ("RIGHTC" + " " + "X" + str(x) + "Y" + str(y) + "EOC")
sock.sendall(command)
elif evt.type == pygame.KEYDOWN:
keyname = pygame.key.name(evt.key)
if evt.key == pygame.K_BACKSPACE:
command = ("BACKSPACE")
sock.sendall(command)
elif evt.key in keylist:
if keyname in key:
command = (keyname)
sock.sendall(command)
def mainloop():
message = []
while 1:
try:
while True:
try:
conn, addr = server.accept()
except socket.error:
break
screen = pygame.display.set_mode((800,600))
clickctrl = Thread(target=ioinput, args=(conn,))
clickctrl.start()
while 1:
d = conn.recv(1024*1024*1)
if not d:
break
else:
message.append(d)
data = ''.join(message)
image = pygame.image.frombuffer(data,(800,600),"RGB")
screen.blit(image,(0,0))
pygame.display.flip()
except Exception as e:
continue
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.setblocking(False)
server.bind((host, port))
server.listen(55000)
print "Listening on %s" % ("%s:%s" % server.getsockname())
Main event loop.
mainloop()
The picture thread will run 3 to six times then die however the keyboard and mouse input layer continues to operate. I suspect that the GIL is getting in my way. Am i correct or am I missing something really simple here? This program is supposed to be a simplistic reverse remote desktop appication.
I found the problem after speaking with a good friend. turns out that my server side while loop was setup so that it would break.
i fixed this by changing:
while 1:
d = conn.recv(1024*1024*1)
if not d:
break
else:
message.append(d)
data = ''.join(message)
image = pygame.image.frombuffer(data,(800,600),"RGB")
screen.blit(image,(0,0))
pygame.display.flip()
to :
while 1:
d = conn.recv(1024*1024*1)
message.append(d)
try:
print("attempting to parse..")
data = ''.join(message)
image = pygame.image.frombuffer(data,(800,600),"RGB")
screen.blit(image,(0,0))
pygame.display.flip()
print("recieved pic")
except Exception as e:
print e
continue
Also, client side on the picture thread i added a time.sleep (1) after the exception handling, otherwise the image does not come though correctly.