Клиент синхронизации Python драматурга по какой-то причине использует асинхронный контекстPython

Программы на Python
Ответить
Anonymous
 Клиент синхронизации Python драматурга по какой-то причине использует асинхронный контекст

Сообщение Anonymous »

Я пытаюсь написать простой скрапер, используя библиотеку Playwright Python
Вот базовый пример того, как я его использую:
from contextlib import contextmanager

from playwright.sync_api import sync_playwright

import asyncio

def is_async():
return asyncio.get_event_loop().is_running()

class BaseScrapper(object):

@property
@contextmanager
def playwright(self):
print(f'BaseScrapper.playwright - is_async={is_async()}')
with sync_playwright() as p:
print(f'BaseScrapper.playwright with - is_async={is_async()}')
yield p

@property
@contextmanager
def browser(self):
print(f'BaseScrapper.browser - is_async={is_async()}')
with self.playwright as p:
print(f'BaseScrapper.browser with - is_async={is_async()}')
yield p.chromium.launch(headless=True)

@contextmanager
def open_page(self, url):
print(f'BaseScrapper.open_page - is_async={is_async()}')
with self.browser as browser:
print(f'BaseScrapper.open_page.with - is_async={is_async()}')
new_page = browser.new_page()

# attach response listener
new_page.on("response", self.intercept_response)

new_page.goto(url, wait_until="domcontentloaded")
yield new_page

def intercept_response(self, response):
pass

class ScrapeTest(BaseScrapper):
@contextmanager
def run(self):
print(f'ScrapeTest.run - is_async={is_async()}')
with self.open_page(url='www.google.com') as page:
print(f'ScrapeTest.run - is_async={is_async()}')
yield page

def run():
print(f'running ... is_async={is_async()}')
s = ScrapeTest()
with s.run() as p:
print(f'run.with is_async={is_async()}')

Я ожидал, что это будет выполняться в контексте синхронизации, но он пытается переключиться на асинхронный режим. Запуск функции run дает следующий результат:
>>> run()
running ... is_async=False
ScrapeTest.run - is_async=False
BaseScrapper.open_page - is_async=False
BaseScrapper.browser - is_async=False
BaseScrapper.playwright - is_async=False
BaseScrapper.playwright with - is_async=True
BaseScrapper.browser with - is_async=True
BaseScrapper.open_page.with - is_async=True

Почему функция «драматург» переключается на асинхронный контекст внутри блока диспетчера контекста? Я пытаюсь запустить там несколько вызовов Django ORM, но у меня не получается
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
Но я пытаюсь запустить его в контексте синхронизации...
Что я пропустил?
Большое спасибо!
еще более простой пример:
from playwright.sync_api import sync_playwright

import asyncio

class BaseScrapper(object):
@property
def playwright(self):
print('basescrapper.playwright')
return sync_playwright().start()

@property
def browser(self):
print('basescrapper.browser')
return self.playwright.chromium.launch(headless=True)

def open_page(self, url):
print('basescrapper.open page')
page = self.browser.new_page()
page.goto(url)
return page

class SampleScrapper(BaseScrapper):
def run(self):
print(f'before - {"async" if asyncio.get_event_loop().is_running() else "sync"}')
page = self.open_page(url='https://www.google.com')
print(f'after - {"async" if asyncio.get_event_loop().is_running() else "sync"}')

def run():
print(f'run 1 - {"async" if asyncio.get_event_loop().is_running() else "sync"}')
s = SampleScrapper()
print(f'run 2 - {"async" if asyncio.get_event_loop().is_running() else "sync"}')
s.run()
print(f'run 3 - {"async" if asyncio.get_event_loop().is_running() else "sync"}')

результат:
>>> run()
run 1 - sync
run 2 - sync
before - sync
basescrapper.open page
basescrapper.browser
basescrapper.playwright
after - async
run 3 - async


Подробнее здесь: https://stackoverflow.com/questions/791 ... ome-reason
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «Python»