Python3(Bot)脚本停止工作
我正在尝试使用QueryServer连接到TeamSpeak服务器以创建一个机器人。我听取了他的建议,但我仍然需要帮助 这是我正在使用的 在编辑之前,这是我的脚本中实际发生的事情的摘要(1个连接):Python3(Bot)脚本停止工作,python,multithreading,python-3.x,Python,Multithreading,Python 3.x,我正在尝试使用QueryServer连接到TeamSpeak服务器以创建一个机器人。我听取了他的建议,但我仍然需要帮助 这是我正在使用的 在编辑之前,这是我的脚本中实际发生的事情的摘要(1个连接): 它连接 它检查通道ID(以及它自己的客户端ID) 它加入了频道,开始阅读所有内容 如果有人说了一个特定的命令,它会执行该命令,然后断开连接 我怎样才能使它不断开连接?如何使脚本保持“等待”状态,以便在执行命令后继续读取 我正在使用Python 3.4.1 我试着学习线程,但不是我很笨,就是它没有按我
我试着学习线程,但不是我很笨,就是它没有按我想象的方式工作。还有另一个“bug”,一旦等待事件发生,如果我没有用命令触发任何东西,它会在60秒后断开连接
#Librerias
import ts3
import threading
import datetime
from random import choice, sample
# Data needed #
USER = "thisisafakename"
PASS = "something"
HOST = "111.111.111.111"
PORT = 10011
SID = 1
class BotPrincipal:
def __init__(self, manejador=False):
self.ts3conn = ts3.query.TS3Connection(HOST, PORT)
self.ts3conn.login(client_login_name=USER, client_login_password=PASS)
self.ts3conn.use(sid=SID)
channelToJoin = Bot.GettingChannelID("TestingBot")
try: #Login with a client that is ok
self.ts3conn.clientupdate(client_nickname="The Reader Bot")
self.MyData = self.GettingMyData()
self.MoveUserToChannel(ChannelToJoin, Bot.MyData["client_id"])
self.suscribirEvento("textchannel", ChannelToJoin)
self.ts3conn.on_event = self.manejadorDeEventos
self.ts3conn.recv_in_thread()
except ts3.query.TS3QueryError: #Name already exists, 2nd client connect with this info
self.ts3conn.clientupdate(client_nickname="The Writer Bot")
self.MyData = self.GettingMyData()
self.MoveUserToChannel(ChannelToJoin, Bot.MyData["client_id"])
def __del__(self):
self.ts3conn.close()
def GettingMyData(self):
respuesta = self.ts3conn.whoami()
return respuesta.parsed[0]
def GettingChannelID(self, nombre):
respuesta = self.ts3conn.channelfind(pattern=ts3.escape.TS3Escape.unescape(nombre))
return respuesta.parsed[0]["cid"]
def MoveUserToChannel(self, idCanal, idUsuario, passCanal=None):
self.ts3conn.clientmove(cid=idCanal, clid=idUsuario, cpw=passCanal)
def suscribirEvento(self, tipoEvento, idCanal):
self.ts3conn.servernotifyregister(event=tipoEvento, id_=idCanal)
def SendTextToChannel(self, idCanal, mensajito="Error"):
self.ts3conn.sendtextmessage(targetmode=2, target=idCanal, msg=mensajito) #This works
print("test") #PROBLEM HERE This doesn't work. Why? the line above did work
def manejadorDeEventos(sender, event):
message = event.parsed[0]['msg']
if "test" in message: #This works
Bot.SendTextToChannel(ChannelToJoin, "This is a test") #This works
if __name__ == "__main__":
Bot = BotPrincipal()
threadprincipal = threading.Thread(target=Bot.__init__)
threadprincipal.start()
在使用2个机器人之前,我测试了在SendTextToChannel连接时启动它,它工作正常,允许我在它将文本发送到频道后做任何我想做的事情。使整个python代码停止的bug只有在由manejadorDeEventos触发时才会发生
编辑1-尝试线程。我把线程技术搞得一团糟,结果是两个客户端同时连接。不知何故,我认为其中一个正在阅读事件,另一个正在回答。脚本不再自动关闭,这是一个胜利,但是克隆连接看起来并不好 编辑2-更新的代码和问题的实际状态。
我设法让双重连接或多或少“正常”工作,但如果房间里60秒没有任何事情发生,它就会断开连接。尝试使用Threading.timer,但无法使其正常工作。整个问题代码已经更新 我想要一个答案,帮助我做两个从频道阅读和回答它,而不需要连接第二个机器人为它(就像它实际上正在做…)如果这个答案也能帮助我理解一种简单的方法,每50秒向服务器查询一次,这样它就不会断开连接,那么我会加分。从查看来看,
recv\u-in\u-thread
不会创建一个循环接收消息的线程,直到退出时间,它创建一个线程,该线程接收单个消息,然后退出:
def recv_in_thread(self):
"""
Calls :meth:`recv` in a thread. This is useful,
if you used ``servernotifyregister`` and you expect to receive events.
"""
thread = threading.Thread(target=self.recv, args=(True,))
thread.start()
return None
这意味着您必须在线程中反复调用recv\u
,而不是只调用一次
我不确定从哪里读取文档,但可能是在接收到的事件触发的回调结束时;我想这就是你的manejadorDeEventos
方法?(或者可能与servernotifyregister
方法有关?我不确定servernotifyregister
用于什么,以及on_event
用于什么…)
manejadorDeEventos
带来了两个侧重点:
- 您已声明
错误。每个方法都必须将manejadorDeEventos
作为其第一个参数。当您传递绑定方法时,如self
,绑定的self.manejadorDeEventos
对象将作为第一个参数传递,在调用方传递任何参数之前。(对于self
s和classmethod
s,也有例外情况,但这些情况不适用于此处。)此外,在该方法中,您几乎可以肯定应该访问staticmethod
,而不是碰巧与self
是同一对象的全局变量self
Bot
- 如果
实际上是manejadorDeEventos
的回调,那么这里有一个竞争条件:如果第一条消息在主线程完成recv\u in_thread
赋值之前出现,那么on_事件
将无法调用事件处理程序。(这正是那种经常百万分之一次出现的bug,当你在部署或发布代码几个月后发现它时,调试起来非常痛苦。)所以,把这两行代码颠倒过来recv\u on_thread
最后一件事:简单地看一下这个库的代码有点令人担忧。它看起来不像是由真正知道自己在做什么的人写的。我在上面复制的方法只有3行代码,但它包括一个无用的
返回None
和一个泄漏的线程
,它永远不能加入
,更不用说让你在收到每个事件后调用这个方法(并产生一个新线程)的整个设计是很奇怪的,更重要的是,这并没有得到真正的解释。如果这是你必须使用的服务的标准客户端库,那么在这件事上你真的没有太多选择,但是如果不是,我会考虑寻找一个不同的库。 @帕克:这是一个更新代码,有一个新问题,而不是一个副本。然而,对OP来说,想办法让这一点更清楚是值得的,因为很多人都会立即做出反应。我不知道该怎么做,特别是当英语不是你的第一语言的时候……也许FAQ有一些指导?作为将来的参考,在本地git存储库中编写这样的代码是值得的,或者至少在对源代码进行重大修改之前备份源文件是值得的。我在项目中也犯过类似的错误,这些错误都会随着备份/源代码管理而消失。我不能再次调用recv_in_线程,因为停止的是python代码,而不是发送到计算机的数据。我强迫它再次调用,错误是“已经收到消息”,正如预期的那样。我不明白为什么整个python代码在SendTextToChannel部分停止,甚至打印函数也停止工作,就像它不是脚本的一部分一样。@Saelyth:好的,这看起来是另一个问题