我是Python 3.3的新手,我开始用套接字写一个小猜谜游戏。但是我一直收到错误ValueError: invalid literal for int() with base 10: ''
我无法理解为什么我在行currentGuess = int(currentGuess)
中出现此错误,因为我在代码中有一个类似的行。如果有人能帮助我,我将非常感激。这是我的服务器和客户端代码。我已经看过其他类似问题的解决方案,但我无法为我工作。
服务器
#!/usr/bin/python
import random
import sys
import math
import socket
l = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
l.bind(("127.0.0.1", 4007))
l.listen(5)
print("Waiting...")
while True:
(s, ca) = l.accept()
print("Connection from", ca)
#Name
s.send("What is your name?". encode())
names = s.recv(1024).decode()
#Guesses
s.send("How many guesses would you like?".encode())
guesses = s.recv(1024).decode()
guesses = int(guesses)
#Random Number
correctNumber = random.randrange(0,10)
print(correctNumber)
#Make Guesses
count = 0
while count < guesses:
s.send("Take a Guess".encode())
currentGuess = s.recv(1024).decode()
currentGuess = int(currentGuess)
if currentGuess == correctNumber:
s.send("You WIN".encode())
if currentGuess != correctNumber:
s.send("Incorrect, Try Again ".encode())
count = count + 1
s.close()
客户端
#!/usr/bin/python
import random
import sys
import math
import socket
s = socket.socket(socket.AF_INET,
socket.SOCK_STREAM)
s.connect(("127.0.0.1", 4007))
print("Wlcome to the numer guessing game")
#Name
print(s.recv(1024).decode())
name = sys.stdin.readline()
s.send(name.encode())
#guesses
print(s.recv(1024).decode())
guesses = sys.stdin.readline()
s.send(guesses.encode())
#Make Guesses
print(s.recv(1024).decode())
currentGuess = sys.stdin.readline()
s.send(currentGuess.encode())
print(s.recv(80).decode())
s.close()
答案 0 :(得分:1)
当您尝试在空字符串上调用int
时出现错误:
>>> int("")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: invalid literal for int() with base 10: ''
这意味着当你这样做时:
currentGuess = s.recv(1024).decode()
currentGuess = int(currentGuess)
currentGuess
设置为''
。也就是说,s.recv(1024)
返回一个空字符串。这仅在连接关闭时发生,因此这意味着客户端已停止向服务器发送数据。
答案 1 :(得分:1)
从s.recv()
获取一个空字符串意味着另一方在连接上调用close
或shutdown
(或者以其他方式中断 - 另一方退出,或某人撕掉以太网线。)
查看您的服务器代码,如果您说要进行3次猜测,则会尝试recv
3次...但客户端只会send
一次,之后会close
} 连接。这意味着服务器上的下一个recv
将返回一个空字符串,这正是您所看到的。
要解决此问题,您需要发送与对方期望的一样多的猜测。像这样:
#Make Guesses
for i in range(int(guesses)):
print(s.recv(1024).decode())
currentGuess = sys.stdin.readline()
s.send(currentGuess.encode())
print(s.recv(80).decode())
s.close()
同时,虽然它没有引起这个特殊问题,但您的代码无法可靠地运行。 Sockets are byte streams, not message streams。我们无法保证每个send
会与另一方的recv
匹配。 recv
可能会将send
的一半或两个send
捆绑在一起。在某些平台上,当你使用localhost,发送小消息,而不是发送太快的东西时,一切都恰好就会发生。在其他平台上,事情大部分时间都有效,但有时却没有。在其他方面,他们经常失败。
最重要的是,正如the docs解释的那样,send
永远不会保证发送整个字符串;这就是它返回实际发送的字节数的原因。您只需使用sendall
即可解决此问题,但这对其他问题没有帮助。
您必须通过设计和实现协议,在TCP字节流之上构建消息流。这可能听起来很可怕,但是一个非常简单的协议,“所有消息以换行符结尾”,只需使用makefile
方法即可实现,如下所示:
s.connect(("127.0.0.1", 4007))
f = s.makefile('r+b')
现在,每次你做其中任何一个:
foo = s.recv(80)
s.send(bar)
...而是做这些:
foo = f.readline().strip()
f.write(bar + '\n')
最后一个不影响你的问题,但应该修复:
在没有参数的情况下调用encode
和decode
几乎总是一个坏主意,特别是对于网络字节。您要求Python使用sys.getdefaultencoding()
中的任何内容对数据进行解码。你能确定客户端和服务器上的默认编码是一样的吗?你能确定它可以处理用户可能输入的任何内容吗?在典型的Windows机器上,它可能类似'cp1252'
,这意味着如果用户键入中文字符,客户端将退出UnicodeError
,这不是非常用户友好。正确的做法是明确使用'utf-8'
。 (这意味着您的协议现在是“所有邮件都是UTF-8,并以换行符结束。”)
如果您正在使用上面建议的makefile
,则可以通过让文件对象为您执行编码来更轻松地解决此问题。就这样做:
f = s.makefile('r+', encoding='utf-8')
然后,您可以省略所有decode
和encode
来电。