微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在python脚本之间传递值数据?

如何解决如何在python脚本之间传递值数据?

在两个不同的 Python 脚本之间进行通信(传递字符串)的正确方式是什么?

我有一个 ui.py 脚本,它利用 PySide6 生成 GUI,我有一个 bot.py 脚本,它侦听不和谐/电报对话并使用异步函数捕获一些关键字。两个脚本都在同一个目录下。

我已将 bot.py 文件中的 Asyncio 事件循环代码放入名为 runscript() 的函数中,并使用 ui.py 中的 multiprocessing.Process 在单击 PySide6 QPushButton 后运行该函数

所以这里的问题是我想在我的 GUI 中显示 bot.py 捕获的关键字,所以我需要将该字符串传递给 ui.py(需要以另一种方式传递字符串 - 从 ui.py 到 bot .py- 在未来),但我不知道如何做到这一点。我尝试过 multiprocessing.Pipe 但这会阻止我的代码,因为脚本会在新消息到达时(使用 Asyncio)从 discord/telegram 中获取消息,而我等不及要发生这种情况。

#bot.py

# do other stuff above here
@discord_client.event
async def on_message(message):
    if message.channel.id in discord_channel_list:
        discord_message = message.content
        selected_symbol = message_analyzer(discord_message)
        print(selected_symbol)

async def discord_connection():
    await discord_client.start(discord_token)

def runscript():
    connection = asyncio.get_event_loop()
    connection.create_task(binance_connection())
    connection.create_task(discord_connection())
    connection.create_task(telegram_connection())
    connection.create_task(connection_check())

    try:
        connection.run_forever()
    except KeyboardInterrupt:
        print("\nShutting down...")
    except:
        print("\nWARN! Shutting down...")

例如我需要获取 selected_symbol 的值并将其传输到 ui.py

#ui.py

import bot

class MainWindow(QMainWindow):
    def __init__(self):
        super().__init__()
        self.start_button = QPushButton("Start")
        self.start_button.clicked.connect(self.run)

    def run(self):
        bot_process = Process(target=bot.runscript)
        bot_process.daemon = True
        bot_process.start()

实现这一目标的正确方法是什么?提前致谢。

解决方法

总的来说,Qt 不是进程安全,因此您不应从另一个进程更新 GUI。另一种方法是创建一个 QThread(或 threading.Thread),它只解析 Queue 的信息并发出带有信息的信号以更新 GUI。另一种选择是使用执行上述操作的 QTimer:监视队列。

class Worker(QObject):
    messageChanged = Signal(str)

def monitoring(p,worker):
    while True:
        try:
            msg = p.recv()
        except EOFError:
            break
        else:
            worker.messageChanged.emit(msg)
r,w = Pipe(duplex=False)
p = Process(target=foo,args=(w,))

worker = Worker()
worker.messageChanged.connect(self.some_slot)

threading.Thread(target=monitoring,args=(r,worker),daemon=True).start()
p.start()

但是使用多处理会增加不必要的复杂性,您可以使用 qasync(python -m pip install qasync) 然后使用 asyncio:

import asyncio
from functools import cached_property
import sys

import discord
from PySide6 import QtCore,QtWidgets
from qasync import QEventLoop,asyncSlot


class DiscordManager(QtCore.QObject):
    connected = QtCore.Signal()
    disconnected = QtCore.Signal()
    messageChanged = QtCore.Signal(discord.message.Message)

    def __init__(self,parent=None):
        super().__init__(parent)
        self.client.event(self.on_message)
        self.client.event(self.on_connect)
        self.client.event(self.on_disconnect)

    @cached_property
    def client(self):
        return discord.Client()

    async def on_message(self,message):
        self.messageChanged.emit(message)

    async def start(self):
        await self.client.start(
            "<TOKEN>"
        )

    async def close(self):
        await self.client.close()

    async def on_connect(self):
        self.connected.emit()

    async def on_disconnect(self):
        self.disconnected.emit()


class MainWindow(QtWidgets.QMainWindow):
    def __init__(self,parent=None):
        super().__init__(parent)
        self.button = QtWidgets.QPushButton("Start")
        self.label = QtWidgets.QLabel(alignment=QtCore.Qt.AlignCenter)

        central_widget = QtWidgets.QWidget()
        lay = QtWidgets.QVBoxLayout(central_widget)
        lay.addWidget(self.button)
        lay.addWidget(self.label)
        self.setCentralWidget(central_widget)

        self.button.clicked.connect(self.handle_clicked)

        self.manager.connected.connect(self.handle_connected)
        self.manager.disconnected.connect(self.handle_disconnected)
        self.manager.messageChanged.connect(self.handle_message)

    @cached_property
    def manager(self):
        return DiscordManager()

    @asyncSlot()
    async def handle_clicked(self):
        if self.button.text() == "Start":
            await self.manager.start()
        else:
            await self.manager.close()

    def handle_message(self,message):
        self.label.setText(message.content)

    def handle_connected(self):
        self.button.setText("Stop")

    def handle_disconnected(self):
        self.button.setText("Start")


def main():
    app = QtWidgets.QApplication(sys.argv)
    loop = QEventLoop(app)
    asyncio.set_event_loop(loop)
    w = MainWindow()
    w.show()
    loop.run_forever()


if __name__ == "__main__":
    main()

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。