如何保持 python 3 脚本(Bot)运行
Posted
技术标签:
【中文标题】如何保持 python 3 脚本(Bot)运行【英文标题】:How to keep a python 3 script (Bot) running 【发布时间】:2014-12-13 10:16:48 【问题描述】:(不是以英语为母语,抱歉英语可能不好。我也是编程新手)。 您好,我正在尝试使用 QueryServer 连接到 TeamSpeak 服务器来制作机器人。经过几天的努力......它工作正常,只有 1 个问题,我被那个问题困住了。
如果您需要检查,这是我正在使用的 TeamSpeak API:http://py-ts3.readthedocs.org/en/latest/api/query.html
这是对我的脚本中实际发生的事情的总结:
-
它连接。
它检查频道 ID(以及它自己的客户端 ID)
加入频道
脚本结束,因此断开连接。
我的问题是:我怎样才能让它不会断开连接?如何使脚本保持“等待”状态,以便在有人在频道中键入“hi bot”时读取?阅读文本和回答它们所需的所有代码似乎都很容易编程,但是我面临一个问题,即我无法让机器人保持“运行”,因为它会在结束运行脚本后立即关闭文件。
更多信息:
我正在使用 Python 3.4.1。
我尝试学习线程http://www.tutorialspoint.com/python/python_multithreading.htm,但要么我很笨,要么它不像我想的那样工作。
在 API 中有一个名为 on_event
的函数,我想一直运行它。机器人代码应该只运行一次,然后保持“等待”直到事件发生。我该怎么做?没有线索。
代码:
import ts3
import telnetlib
import time
class BotPrincipal:
def Conectar(ts3conn):
MiID = [i["client_id"] for i in ts3conn.whoami()]
ChannelToJoin = "[Pruebas] Bots"
ts3conn.on_event = BotPrincipal.EventHappened()
try:
BuscandoIDCanal = ts3conn.channelfind(pattern=ChannelToJoin)
IDCanal = [i["cid"] for i in BuscandoIDCanal]
if not IDCanal:
print("No channel found with that name")
return None
else:
MiID = str(MiID).replace("'", "")
MiID = str(MiID).replace("]", "")
MiID = str(MiID).replace("[", "")
IDCanal = str(IDCanal).replace("'", "")
IDCanal = str(IDCanal).replace("]", "")
IDCanal = str(IDCanal).replace("[", "")
print("ID de canal " + ChannelToJoin + ": " + IDCanal)
print("ID de cliente " + Nickname + ": " + MiID)
try:
print("Moving you into: " + ChannelToJoin)
ts3conn.clientmove(cid=IDCanal, clid=MiID) #entra al canal
try:
print("Asking for notifications from: " + ChannelToJoin)
ts3conn.servernotifyregister(event="channel", id_=IDCanal)
ts3conn.servernotifyregister(event="textchannel", id_=IDCanal)
except ts3.query.TS3QueryError:
print("You have no permission to use the telnet command: servernotifyregister")
print("------- Bot Listo -------")
except ts3.query.TS3QueryError:
print("You have no permission to use the telnet command: clientmove")
except ts3.query.TS3QueryError:
print("Error finding ID for " + ChannelToJoin + ". telnet: channelfind")
def EventHappened():
print("Doesn't work")
# Data needed #
USER = "thisisafakename"
PASS = "something"
HOST = "111.111.111.111"
PORT = 10011
SID = 1
if __name__ == "__main__":
with ts3.query.TS3Connection(HOST, PORT) as ts3conn:
ts3conn.login(client_login_name=USER, client_login_password=PASS)
ts3conn.use(sid=SID)
print("Connected to "+HOST)
BotPrincipal.Conectar(ts3conn)
【问题讨论】:
附带说明,这不是您使用类的方式。您的Conectar
应该采用self
参数,并且您的主代码应该构造一个BotPrincipal
实例并在该实例上调用Conectar
方法等。这是3 个消除错误的组合使这种工作,这可能不是你想要依赖的东西。
只是添加到 abarnets 笔记,看看 Python's official documentation on classes 或一些 different tutorials。
因为我从来没有真正学过任何编程语言,而且我只用谷歌尽我所能,我可以看到我失败的地方。我现在正在检查该网站并尝试解决问题。感谢您的帮助。
【参考方案1】:
快速浏览 API,您似乎需要明确告诉 ts3conn
对象等待事件。似乎有几种方法可以做到这一点,但ts3conn.recv(True)
似乎是最明显的:
如果
recv_forever
为真,则在收到所有未提取的响应之前或永远阻塞。
大概当每个命令进来时,它会调用你的 on_event
处理程序,然后当你从那里返回时,它会继续等待下一个命令。
我不知道您是否需要这里的线程,但recv_in_thread
的文档听起来像您可能:
在线程中调用
recv()
。如果您使用servernotifyregister
并且您希望接收事件,这很有用。
您大概想要同时获取 servernotify 事件和命令,我猜这个库的编写方式您需要线程吗?如果是这样,只需调用ts3conn.recv_in_thread()
而不是ts3conn.recv(True)
。 (如果您查看the source,所做的只是启动一个后台线程并在该线程上调用self.recv(True)
。)
【讨论】:
让我看看我是否理解这一点。我应该在 def EventHappened(): 中调用 ts3conn.recv_in_thread(): 它会创建自己的线程,所以我不需要自己做? @Saelyth:不在EventHappened
内部,要么在Conectar
的末尾,要么在Conectar
返回之后的主代码中。是的,它创建了自己的线程,所以你不必这样做。除非您尝试在处理程序中执行依赖于变异全局变量或其他共享变量的操作,否则您甚至不必担心线程存在这一事实。
我有一个与此相关的问题。现在机器人在一个线程中读取 telnet 控制台事件(这是完美的),但是如果我让机器人做其他事情,它会停止读取并且似乎关闭了线程(我认为)。我使用了类似“如果您阅读 X,则发送消息 Y”之类的内容。但在那之后,它不会再等待事件了。从 API 来看,我似乎无法理解为什么 on_event 停止工作。
@Saelyth:如果你有一个新问题,你应该问一个新的答案。特别是因为我对这个 API 一无所知,一个新问题可能会吸引知道的人的答案。但是如果线程要结束了,那可能是你每发一条消息后都要再次调用recv_in_thread
?
做到了。我也尝试使用我应该使用的类(我想,我真的很感谢你的帮助),链接在这里:***.com/questions/26490533/…以上是关于如何保持 python 3 脚本(Bot)运行的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 Rails 让我的 Twitter Bot 保持清醒?