multiasting TypeError: argument must be an int, or have a fileno() method

multiasting TypeError: argument must be an int, or have a fileno() method

我有一个问题,我已经用 gui 创建了多播,我的程序需要 sys.stdin 但我的 gui 中有文本 - 字符串。

sockets_list = [sys.stdin, server] 
read_sockets,write_socket, error_socket  = select.select(sockets_list,[],[])

此代码无效

def message(self, event):
    mess = self.write.get() 
    self.sockets_list = [mess, self.server]
    self.read_sockets, write_socket, error_socket  = select.select(self.sockets_list,[],[]) 
    print self.sockets_list
    self.write.delete(0, Tkinter.END)
    if mess != '':
      self.mess1.configure(state = NORMAL)
      self.all_users.append('Adam')
      for socks in self.read_sockets:
        if socks == self.server:
            message = socks.recv(2048)
            self.mess1.insert(Tkinter.END, '%s> %s \n' %(self.nick, message)) #wyswietla wprowadzony tekst
            self.mess1.see(Tkinter.END) 
        else:
            message = mess
            self.server.send(message)
            print self.nick
            print message
      self.mess1.see(Tkinter.END) 
      self.mess1.configure(state = DISABLED)

我想在多播基础上创建一个 Messenger 我从一个客户端发送消息 - 我转到服务器并将其发送给其余客户端。问题是我不能使用在 gui 中输入的消息,它在终端中有效

所有代码

web_pr_less2_client.py - 客户

dup.py - 服务

https://github.com/Antoni-Hp/Web_programing/tree/master/Python_web_programing_less2

题主所说的这里的问题是"the code doesn't work"。虽然作者试图为导致特定异常抛出的特定错误找到解决方案,但仅修复它并不能解决代码不工作的问题。似乎作者才刚刚开始学习如何编写 GUI 应用程序代码。

我对 Tkinter 知之甚少,但无论如何我都会通过解释我在这里看到的问题来提供帮助。

  1. 问题中出现的 message 方法被调用以响应 "submit message" 事件。但是,此方法还会尝试读取可能在任何给定时间从服务器到达的消息。这意味着用户在自己发送消息之前不会看到来自服务器的任何新消息。此 "read from server" 段代码应从该方法中移出并单独处理。

    现在,正如我之前所说,我不熟悉 Tkinter,所以我不能说我知道这里最好的方法是什么,但通常 GUI 应用程序需要通过等待来监听后台事件通过回调函数或轮询我们在后台等待的事件来获取 "ready" 事件的到达。这是如何实现的取决于所使用的技术(定时器、线程、OS API 回调函数)。

    你的情况:

    1.1。将读取操作提取到单独的方法中。
    1.2.使用 Tkinter 计时器定期调用此方法。
    1.3. select() 在短超时的套接字上(尝试 0.01
    1.4.如果套接字已准备好读取,请读取它并将其附加到聊天 window.

    这是一个原始的解决方案,因为 0.01 超时会使您的应用程序停止,并且在生产级软件中不应在主线程中完成,但这是一个很好的起点。

  2. 消息提交时抛出的异常是由于尝试使用从文本输入小部件获得的 mess 变量,就好像它是 I/O 句柄一样,而在实际上是 str。 I/O 句柄是文件、文件描述符、套接字、管道。 str 是一种数据类型,不能传递给 select()。但是,您可以毫不费力地通过套接字发送它,即。

    def message(self, event):
        message = self.write.get()
        self.write.delete(0, Tkinter.END)
        self.server.send(message)
        self.mess1.configure(state=NORMAL)
        self.mess1.insert(Tkinter.END, '%s> %s \n' %(self.nick, message))
        self.mess1.see(Tkinter.END)
        self.mess1.configure(state=DISABLED)
    

此外,除了手头的问题,我的一般建议是:

您的代码不遵循 PEP8 样式建议。虽然这不会影响您的软件功能,但您可以重新考虑是否遵循这些规则。它们是由 Python 语言的作者官方推荐的,您在网上找到的大多数 Python 代码很可能会遵循它们。 运行 flake8 检查您的代码显示 351 次违规。

我还建议将重点放在符号的更精确命名上。

  • def message 应该是 def on_message_send_requested(我使用了 on 前缀,因为由于存在 event 参数,此方法只能用作回调) ,
  • self.server 应该是 self.connection_socket,
  • mess 应该是 message,
  • self.write 应该是 self.text_input

我使用了 after() 函数并且它有效。

@ZalewaPL 谢谢你的帮助:)

解决方案:

 def read_from_server(self):
    read_sockets, write_socket, error_socket = 
    select.select([self.connection_socket],[],[], 0.1)
    for socks in read_sockets:
      if socks == self.connection_socket:
        message = socks.recv(2048)
        message = message.split(";;")
        self.mess1.configure(state = NORMAL)
        self.mess1.insert(Tkinter.END, '%s> %s \n' %(message[0], message[1]))
        self.mess1.see(Tkinter.END)
        self.mess1.configure(state = DISABLED)
    self.main.after(1, self.read_from_server)


  def on_message_send_requested(self, event):
    message = self.text_input.get() # pobiera tekst z okienka write
    self.text_input.delete(0, Tkinter.END)
    if message != '':
      self.mess1.configure(state = NORMAL)
      send_message = "%s;;%s" %(self.nick, message)
      self.connection_socket.send(send_message)
      self.mess1.insert(Tkinter.END, '%s> %s \n' %(self.nick, message)) 
      self.mess1.see(Tkinter.END) #pokazuje zawsze najnowszy wpis
      self.mess1.configure(state = DISABLED)