I am making an online game using the sockets module and pygame in python.
def read_pos(str):
if str is not None:
string = str.split(",")
return int(string[0]), int(string[1])
else:
pass
def make_pos(tup):
return str(tup[0]) + "," + str(tup[1])
def redrawWindow(win,player, player2):
win.fill((255,255,255))
player.draw(win)
player2.draw(win)
pygame.display.update()
def main():
run = True
n = Network()
startPos = read_pos(n.getPos())
p = Player(startPos[0],startPos[1],100,100,(0,255,0))
p2 = Player(0,0,100,100,(255,0,0))
clock = pygame.time.Clock()
while run:
clock.tick(60)
p2Pos = read_pos(n.send(make_pos((p.x, p.y))))
p2.x = p2Pos[0]
p2.y = p2Pos[1]
p2.update()
This is the code I'm using in my client. in my server, the code is as follows
def convertPos(str):
if str is not None:
str = str.split(",")
return int(str[0]), int(str[1])
else:
pass
def make_pos(tup):
return str(tup[0]) + "," + str(tup[1])
pos = [(0,0),(100,100)]
def threaded_client(conn,player):
conn.send(str.encode(make_pos(pos[player])))
reply = " "
while True:
try:
data = conn.recv(2048).decode()
pos[player] = data
if not data:
print("Disconnected")
break
else:
if player == 1:
reply = (pos[0])
else:
reply = (pos[1])
print("Received: ", data)
print("Sending : ", reply)
conn.sendall(str.encode(make_pos(reply)))
except:
break
print("Lost connection")
conn.close()
I am getting the error of ValueError: invalid literal for int() with base 10: ' '.
Can someone tell me why this is happening? The value of str in the function of convertPos() is coming in as a tuple which I am converting into a string and after that into an integer.
As you have converted it to string, the format you have is (x,y), you need to remove the brackets. You need to rewrite your convertPos function as:
def convertPos(str):
if str is not None:
str=str.strip("()")
str = str.split(",")
return int(str[0]), int(str[1])
EDIT You are not using the else part, so you can remove it.
And as #Azat Ibrakov says, you should not convert the tuple to an string, but if you need to do it, you can use ast.literal_eval like this:
import ast
def convertPos(str):
return ast.literal_eval(str)
or use it directly in place of the convertPos function.
Obviously - as others have pointed out, the returned error is because you're trying to convert an empty string (or spaces) to an integer.
But the real issue is that the incoming co-ordinate is malformed. The code is not catching this error. You can write lots of code to determine what the error is, and report an accurate error. Or just plough-on as if everything is fine, but also catch any exception with a reasonable error message.
def convertPos(str):
coord = None
try:
parts = str.split( ',', 2 )
x = int( parts[0] )
y = int( parts[1] )
coord = ( x, y )
except:
raise ValueError( 'Malformed co-ordinate string [' + str.strip() + ']' )
return coord
I suspect the socket code is not buffering a full packet, and maybe what's being processed is something like 122,, whereas the socket buffering needs to keep reading until a full co-ordinate has arrived.
So you could space-pad your co-ordinates to say a block of 11 characters - that way you know you must have received 11 characters to have a valid co-ordinate string. Alternatively use and end-of-coord marker, like a |, and then the socket code keeps buffing the input co-ordinate until that | arrives.
Related
This program essentially encodes and decodes a message and code respectively. I only did the decoding part so far. However I keep getting an EOF error even though I made sure to end parentheses, checked my syntax and kept tampering with it. Unfortunately no luck. Anyone know why this error keeps popping up? I would greatly appreciate it. Also I copied both files that i'm using.
from LetterCodeLogic import LCL
def main():
print("Welcome to the LetterCode program")
choice = getChoice()
while choice !=0:
if choice == 1:
#Encode logic...
print()
elif choice == 2:
#Decode logic...
msg = input("Enter your numbers to decode (separate with commas): ")
#send msg to Decode function in LCL class (LetterCodeLogic.py file)
result = LCL.Decode(msg)
print("Your decoded message is: \n" + result)
else:
print("Unknown process...")
print()
choice = getChoice()
print("Thanks for using the Letter Code program")
def getChoice():
c = int(input("Choice? (1=Encode, 2=Decode, 0=Quit): "))
return c
if __name__ == "__main__":
main()
class LCL:
"""Encode/Decode Functions"""
#staticmethod
def Decode(msg):
#separate numbers from msg string (e.g., "1,2,3")
nums = msg.split(",") #produces list of separate items
result = ""
for x in nums:
try:
n = int(x.strip()) #remove leading/trailing spaces...
if n == 0:
c = " "
elif n < 0 or n > 26:
c = "?"
else:
#ASCII scheme has A=65, B=66, etc.
c = chr(n+64)
except ValueError:
c = "?"
result += c #same as: result = result + c
return result
#staticmethod
def Encode(msg):
the "#staticmethod" and "def Encode()" function was empty and that was the end of line parsing error. When I was coding this and ran it, it ran with no problems. So I removed it for the time being.
I am making a bot that links users to the SCP Wiki (The foundation one). I want my bot to be able to pick up a SCP classification (i.e. SCP-370) and return a message with the link to the scp wiki, with that number (i.e. http://scp-wiki.net/scp-370)
I've tried a few things, such as:
def scp_url(num):
return "http://www.scp-wiki.net/scp-" + num
def scp_link(num):
return "[SCP-" + num + "](" + scp_url(num) + ")"
#client.event
async def on_message(message):
if "SCP" in message.content:
msg = scp_link
await client.send_message(message.channel, msg)
Or:
if int in message.content:
int = num
I just can't find a way to grab the numbers from the message.
Any help is appreciated.
For that, you need to know the format of the input.
From your question I see it's not command because it will check every message for SCP string. But will the string be formatted as SCP-1 or SCP-001 or SCP 1?
You need to take care of all of those cases or just make 1 selected case and deal with that. Here's my fully commented code which deals with all 3 cases:
# Number separator is character between SCP and a number, example with space:
# SCP 1
NUMBER_SEPARATOR = " "
MAXIMUM_SCP_NUMBER = 4999
def get_scp_link(message_content):
word_list = message_content.split(NUMBER_SEPARATOR)
scp_number = _extract_scp_number(word_list)
if scp_number is not None:
try:
# int(scp_number) takes care if users already entered 001
# because it makes it equal to 1
formatted_number = _format_scp_number(int(scp_number))
return _build_scp_url(formatted_number)
except Exception:
return None
# #param word_list a list of strings
# #return integer or None if error
def _extract_scp_number(word_list):
captured_scp_number = None
for index, word in enumerate(word_list):
if word == "SCP":
# We're gonna return the word after the current word (index+1)
# But we have to make sure that the next word exists in the list
# otherwise we will get IndexError exception
if index + 1 < len(word_list):
captured_scp_number = word_list[index + 1]
else:
return None
# If we captured a string in the for loop we have to make sure that that
# string is actually a number and not some random word example "SCP blabla"
if captured_scp_number is not None and captured_scp_number.isdigit():
return captured_scp_number
return None
# Formats number as a string in format 001-MAXIMUM_SCP_NUMBER
# This allows users to enter 1 instead of 001.
#
# #param number a positive integer to be formatted
# #return string in format 001-MAXIMUM_SCP_NUMBER or raise Exception if error
def _format_scp_number(number):
if number == 0:
raise Exception("SCP 0 doesn't exist!")
elif number > MAXIMUM_SCP_NUMBER:
raise Exception("SCP number too high! Entry doesn't exist!")
elif number < 10:
return "00" + str(number)
elif number < 100:
return "0" + str(number)
else:
return str(number)
# #param formatted_scp_number a string in format 001-MAXIMUM_SCP_NUMBER
# #return string representing URL to SCP-number web page
def _build_scp_url(formatted_scp_number):
base_url = "http://www.scp-wiki.net/scp-"
prefix = "[SCP-" + formatted_scp_number + "]"
return prefix + base_url + formatted_scp_number
#client.event
async def on_message(message):
if "SCP" in message.content:
scp_link = get_scp_link(message.content)
if scp_link is not None:
await client.send_message(message.channel, scp_link)
Comment below for any questions or suggestions.
I'm currently writing a test function for class to test provided cases on provided solution code. However I'm running into an issue where a print statement is executing when I don't want it to.
This is the provided solution that I'm testing:
def alphapinDecode(tone):
phone_num = ''
if checkTone(tone): #or checkTone2
while len(tone) > 0:
# retrieve the first tone
next_tone = tone[0:2]
tone = tone[2:]
# find its position
cons = next_tone[0]
vow = next_tone[1]
num1 = consonants.find(cons)
num2 = vowels.find(vow)
# reconstruct this part of the number -
# multiply (was divided) and add back
# the remainder from the encryption division.
phone = (num1 * 5) + num2
# recreate the number
# by treating it as a string
phone = str(phone)
# if single digit, not leading digit, add 0
if len(phone) == 1 and phone_num != '':
phone = '0' + phone
phone_num = phone_num + phone
# but return in original format
phone_num = int(phone_num)
else:
print('Tone is not in correct format.')
phone_num = -1
return phone_num
Here's the (partially done) code for the test function I have written:
def test_decode(f):
testCases = (
('lo', 43),
('hi', 27),
('bomelela', 3464140),
('bomeluco', 3464408),
('', -1),
('abcd', -1),
('diju', 1234),
)
for i in range(len(testCases)):
if f(testCases[i][0]) == testCases[i][1] and testCases[i][1] == -1:
print('Checking '+ f.__name__ + '(' + testCases[i][0] + ')...Tone is not in correct format.')
print('Its value -1 is correct!')
return None
When executing test_decode(alphapinDecode), I get this:
Tone is not in correct format.
Checking alphapinDecode()...Tone is not in correct format.
Its value -1 is correct!
Tone is not in correct format.
Checking alphapinDecode(abcd)...Tone is not in correct format.
Its value -1 is correct!
As you can see, because of the print statement in alphapinDecode(I think), it is printing an extra "Tone is not in correct format." above the print statement I have written.
How would I prevent this print statement from executing, and why is it printing if the print statement I wrote in my test function doesn't ask for the result of alphapinDecode?
We are not allowed to alter the code of the given solution.
I'm fairly new to stackOverflow, so sorry for any formatting issues. Thank you!
Edit: Fixed the idents of the test_decode function
One easy solution would be to pass an extra parameter say, a boolean variable debug to the function. That would go something like this.
def func1(var1, debug):
if debug:
print("Printing from func1")
# Do additional stuff
Now when you call it. You now have the option of setting the debug variable.
func1("hello", debug=True) # will print the statement
func1("hello", debug=False) # will not print statement.
If you cannot modify the called function. Then you can follow this method. explained by #FakeRainBrigand here.
import sys, os
# Disable
def blockPrint():
sys.stdout = open(os.devnull, 'w')
# Restore
def enablePrint():
sys.stdout = sys.__stdout__
print 'This will print'
blockPrint()
print "This won't"
enablePrint()
print "This will too"
duration = inputScriptLine.split(' ', 1)[1]
if type(duration) == str:
print ' Error: Sleep duration "' + duration + '" is not numeric'
given SLEEP 50, I get Error: Sleep duration "50" is not numeric
I am not too concerned as to why, I just want to know how I can code so that SLEEP 50 is valid and SLEEP APNOEA is not.
Use isdigit():
if not duration.isdigit():
print 'Error: Sleep duration "' + duration + '" is not numeric'
It would check whether all characters in duration are digits or not.
If you want to accept more than just ints you should cast to float:
def is_numeric(s):
try:
float(s)
return True
except ValueError:
return False
duration = inputScriptLine.split(' ', 1)[1]
if not is_numeric(duration):
print(' Error: Sleep duration {} is not numeric'.format())
float("1.0"), float("1"), float("1.5") etc.. would all return True but int("1.0"), int("1.5") etc..would also return False which if you are actually looking for numeric input would be wrong.
If you want to make sure you also get a positive number, store the result after you cast and return f > 0:
def is_positive_numeric(s):
try:
f = float(s)
return f > 0
except ValueError:
return False
try:
duration = int(duration)
except:
pass
This will attempt to convert it to an int, if it's not numeric it will fail and stay a string.
DeveloperXY's solution is cleaner, but if you want to use the value as an int later on, my solution is useful.
duration = inputScriptLine.split(' ', 1)[1]
try:
duration = int(duration)
except ValueError:
print ' Error: Sleep duration "' + duration + '" is not numeric'
You are checking if the input is a string. It will be - you've just used the split command on a string.
You need to check if the string contains only numeric characters, with .isdigit().
Note that this won't accept negative inputs, but you don't want those as this is a time.
So your new code is:
duration = inputScriptLine.split(' ', 1)[1]
if not duration.isdigit():
print 'Error: Sleep duration "' + duration + '" is not numeric'
I am trying to write a basic driver to control a device that only interacts with hyperterminal. All the inputs expect HT formated data and all of the returns include copious equal signs, newlines, and spaces in order to get the formatting correct for human visualization. I am pretty sure that the returns are generating trouble, as I am throwing exceptions a lot, but I am not sure how else I can handle it. Does anyone know of a better way to do this?
Device manual: http://us.startech.com/media/products/PCM815SHNA/Manuals/PCM815SHNA.pdf
import visa
import re
class iopower8(visa.SerialInstrument):
#initialization
def __init__(self,loc):
visa.SerialInstrument.__init__(self,loc)
self.term_chars = '\r' #set terminal characters
self.write('\r\r') #start faux 'Hyperterminal'
def on(self, bank, out):
self.ask("on " + str(bank) + " " + str(out))
for i in range (1,3):#read buffer into void to prevent issues
try:
self.read_raw()
except(visa_exceptions.VisaIOError):
self.buffer_clear()
break
return self.status(bank, out)
def off(self, bank, out):
self.ask("of " + str(bank) + " " + str(out))
for i in range (1,3):#read buffer into void to prevent issues
try:
self.read_raw()
except(visa_exceptions.VisaIOError):
self.buffer_clear()
break
return self.status(bank, out)
def status(self, bank, port): #enter bank and port # you want to check
self.ask("st " + str(bank))
result = 'Error' #send error message regardless
for i in range (1,13):#all 12 lines need to be read out of the buffer to prevent issues later
try:
stuff = self.read()#read the line to a holding srting, and dump in void if wriong line to clear buffer
if stuff.strip() == ('='*44):
break
except(visa_exceptions.VisaIOError):
break
for i in range(1,9):
try:
stuff = self.read()#read the line to a holding string, and dump in void if wriong line to clear buffer.
if i == port: #this offset will get you to the line with the relevant port's status
result = re.match('(.*?)(ON|OFF)', stuff) #regex to the find the on/off status
#convert to boolean
if result.group(2) == 'ON':
result = True
elif result.group(2) =='OFF':
result = False
else:
result = 'ERROR'
except(visa_exceptions.VisaIOError):
self.buffer_clear()
break
return result
def buffer_clear(self): #in case of buffer jamming
while True:
try:
self.read_raw()
except(visa_exceptions.VisaIOError):
break
def all_on(self, bank):
self.ask("on " + str(bank) + " 0")
for i in range (1,3):#read buffer into void to prevent issues
try:
hold = self.read_raw()
except(visa_exceptions.VisaIOError):
self.buffer_clear()
break
def all_off(self, bank):
self.ask("of " + str(bank) + " 0")
for i in range (1,3):#read buffer into void to prevent issues
try:
self.read_raw()
except(visa_exceptions.VisaIOError):
self.buffer_clear()
break
There's nothing special about HiperTerminal. The end of line character is usually '\r\n' or '\n' alone.