如何保持Python 3脚本(机器人)运行

5 投票
1 回答
2971 浏览
提问于 2025-04-28 04:30

(英语不是母语,可能表达得不太好。 我也是编程新手)。
你好,我正在尝试通过QueryServer连接到一个TeamSpeak服务器,以制作一个机器人。经过几天的努力……它终于可以工作了,但还有一个问题让我卡住了。

如果你需要查看,我正在使用的TeamSpeak API是: http://py-ts3.readthedocs.org/en/latest/api/query.html

以下是我的脚本实际发生的事情的总结:

  1. 它成功连接。
  2. 它检查频道ID(还有它自己的客户端ID)
  3. 它加入了频道
  4. 脚本结束,所以它断开了连接。

我的问题是:我该如何让它不断开连接?我该如何让脚本保持在“等待”状态,以便可以读取如果有人在频道里输入“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)
暂无标签

1 个回答

3

从这个API的简单浏览来看,你需要明确告诉ts3conn对象去等待事件。似乎有几种方法可以做到这一点,但ts3conn.recv(True)看起来是最直接的选择:

这个方法会一直阻塞,直到所有未获取的响应都被接收,或者如果recv_forever为真,就会一直等待。

可以推测,每当有命令到达时,它会调用你的on_event处理器,然后当你从这个处理器返回时,它会继续等待下一个命令。

我不确定你是否需要使用线程,但recv_in_thread的文档让人感觉可能需要:

这个方法会在一个线程中调用recv()。如果你使用了servernotifyregister并且期望接收事件,这个方法会很有用。

你可能想同时接收servernotify事件和命令,而我猜这个库的写法是需要线程来实现的?如果是这样的话,就用ts3conn.recv_in_thread()代替ts3conn.recv(True)。如果你查看源代码,你会发现它只是启动了一个后台线程,并在那个线程中调用self.recv(True)

撰写回答