Не могу переключиться на другую тему

Я пытаюсь создать бота Telegram, который может отправлять снимок экрана веб-страницы.

Я использую python-telegram-bot для взаимодействия с Telegram и python-playwright для получения снимков экрана страницы. Проблема с моим кодом в том, что я получаю следующую ошибку с Playwright:

greenlet.error: cannot switch to a different thread

Это происходит потому, что я объявляю browser = p.chromium.launch(headless=True, args=args) вне функции, которая выполняется при вызове команды Telegram. Проблема в том, что запуск браузера при каждом вызове команды Telegram замедляет работу моего кода примерно на 3 секунды. Как я могу объявить browser глобально? Возможно ли это вообще?

from telegram import InlineKeyboardButton, InlineKeyboardMarkup, ParseMode
from telegram.ext import Updater, CommandHandler, ChatMemberHandler, CallbackQueryHandler
from telegram.error import Unauthorized, BadRequest
from playwright.sync_api import sync_playwright

args = [
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--use-gl=egl",
    ]

p = sync_playwright().start()
browser = p.chromium.launch(headless=True, args=args)

def start(update, context):
    page = browser.new_page()
    page.goto("https://google.com")
    page.screenshot(path = "example.png")
    page.close()
    context.bot.send_photo(chat_id=update.effective_chat.id, photo=open("example.png", "rb"))  


updater = Updater('TOKEN', use_context=True, workers=124)
updater.dispatcher.add_handler(CommandHandler('start', start, run_async=True))
updater.start_polling()
updater.idle()

возможно, вам следует использовать queue для отправки информации в другой поток и другую очередь для получения результата. И browser должен запустить цикл, который проверит, есть ли URL-адрес в очереди, создаст снимок экрана и отправит его обратно queue - а затем дождется следующего сообщения в queue

furas 20.04.2024 20:23

добавив два комментария: 1) Я рекомендую вам отозвать токен, который вы опубликовали для своего бота «ds1testbot». 2) JayK23, ваш код написан для PTB версии 13.15 или старше, которая больше не поддерживается командой PTB. Ответ, предоставленный Мохаммедом Алмалки, по сути, переписывает весь ваш код в PTB v20.x или новее, используя asyncio Pythons как в PTB, так и в playwright.

CallMeStag 21.04.2024 17:44

Спасибо! Я удалил токен. Я пытаюсь найти способ не запускать экземпляр браузера каждый раз, когда вызывается команда, поскольку это занимает несколько секунд. Я пытаюсь найти способ объявить это глобально, не получая ошибки «невозможно переключиться на другой поток».

JayK23 21.04.2024 18:18
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
3
276
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я работал над этим и многое изменил в вашем коде,

Я создал бота, чтобы попробовать, пока не доведу его до конца.

Я изменил код на асинхронный код.

это последний код:

import telegram
from telegram import Update
from telegram.ext import MessageHandler, CommandHandler, Application, ContextTypes, filters
from playwright.async_api import async_playwright

args = [
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--use-gl=egl",
    ]


# Replace 'YOUR_API_TOKEN' with the API token you received from BotFather.
API_TOKEN = 'yours'


async def download_screan_shot(link = "www.google.com", id_of_chat=None, update_to_use_it_to_send_the_file=None):
    file_name =f"{id_of_chat}_example.png"

    async with async_playwright() as p:
        browser = await p.chromium.launch()
        page = await browser.new_page()
        await page.goto(link)
        await page.screenshot(path=file_name)
        await browser.close()

    await update_to_use_it_to_send_the_file.message.reply_photo(file_name)



async def messages(update, context):
    the_gotten_message = update.message.text
    if "www" in the_gotten_message:
        await download_screan_shot(link=the_gotten_message, id_of_chat=update.message.from_user.id, update_to_use_it_to_send_the_file=update)
    else:
        await update.message.reply_text(update.message.text)


app = Application.builder().token(API_TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT,messages))
app.run_polling()

а это скриншот моего бота:

Я надеюсь, что это сработает для вас.

по поводу количества отправленных ссылок, это неудачные попытки.

Редактировать:

поскольку вы сказали, что хотите запустить браузер один раз, я не нашел для этого решения, но сделал это, используя плохую идею.

он запускает браузер один раз, затем сохраняет его в публичном доступе в списке, а затем использует этот активный браузер.

это мой новый код:

import telegram
from telegram import Update
from telegram.ext import MessageHandler, CommandHandler, Application, ContextTypes, filters
from playwright.async_api import async_playwright
from playwright.sync_api import sync_playwright

args = [
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--use-gl=egl",
    ]


# Replace 'YOUR_API_TOKEN' with the API token you received from BotFather.
API_TOKEN = 'yours'


opened_browser = []


async def download_screan_shot(link = "www.google.com", id_of_chat=None, update_to_use_it_to_send_the_file=None):
    file_name =f"{id_of_chat}_example.png"

    # playwright = sync_playwright().start()
    # browser = playwright.chromium.launch()
    # page = browser.new_page()
    # page.goto("https://playwright.dev/")
    # page.screenshot(path = "example.png")
    # browser.close()


    if (not opened_browser):
        playwright = await async_playwright().start()
        browser = await playwright.chromium.launch()
        opened_browser.append(browser)

    page = await opened_browser[0].new_page()
    await page.goto(link)
    await page.screenshot(path=file_name)
    await page.close()
    # await opened_browser[0].close()

    await update_to_use_it_to_send_the_file.message.reply_photo(file_name)



async def messages(update, context):
    the_gotten_message = update.message.text
    if "www" in the_gotten_message:
        await download_screan_shot(link=the_gotten_message, id_of_chat=update.message.from_user.id, update_to_use_it_to_send_the_file=update)
    else:
        await update.message.reply_text(update.message.text)


app = Application.builder().token(API_TOKEN).build()
app.add_handler(MessageHandler(filters.TEXT,messages))
app.run_polling()


если честно, я не увидел никакой разницы в производительности, а также не знаю, что там происходит.

это просто попытка дать вам представление.

вы можете сделать то же самое в своем коде >>> Я не делал этого, потому что думаю, что вы используете старую версию библиотеки Telegram, и поэтому я столкнулся со многими ошибками, когда пробовал ваш код с той версией, которая у меня есть.

скажи мне.

Эй, большое спасибо за ваш ответ! Проблема в том, что я ищу способ не запускать новый экземпляр браузера при каждой команде.

JayK23 21.04.2024 18:13

@JayK23, можешь проверить редактирование, пожалуйста.

Mohammed almalki 24.04.2024 08:28

Другие вопросы по теме