【问题标题】:Is it better to import static or dynamic with I/O Bound application使用 I/O Bound 应用程序导入静态还是动态更好
【发布时间】:2021-06-06 10:59:50
【问题描述】:

我一直在开发一个 I/O 绑定应用程序,它是一个新闻网络爬虫。我有一个文件,我可以在其中启动我们可以称为“monitoring.py”的脚本,并通过选择我要监控的新闻公司添加一个参数,例如monitoring.py --company=sydsvenskan 然后会触发 sydsvenskan 网络爬虫。

它的作用基本上是这样的:

scraper.py

from __future__ import annotations

from abc import abstractmethod
from typing import ClassVar, Dict

import requests

from lib.vendors.sydsvenskan import sydsvenskan
from lib.vendors.bbc import bbc


class Scraper:
    scrapers: ClassVar[Dict[str, Scraper]] = {}
    domain: ClassVar[str]

    def __init_subclass__(cls) -> None:
        Scraper.scrapers[cls.domain] = cls

    @classmethod
    def for_url(cls, domain, url) -> Scraper:
        return cls.scrapers[domain](url)

    @abstractmethod
    def scrape_feed(self):
        pass

    @abstractmethod
    def scrape_product(self):
        pass


class SydsvenskanScraper(Scraper):
    domain = 'sydsvenskan'

    def __init__(self, url):
        self.url = url

    def scrape_feed(self):
        with requests.get(self.url) as rep:
            # FIXME Better way than this atleast :P
            if rep:
                return sydsvenskan().scrape_feed(rep=rep)

    def scrape_product(self):
        with requests.get(self.url) as rep:
            # FIXME Better way than this atleast :P
            if rep:
                return sydsvenskan().scrape_product(rep=rep)


class BBCScraper(Scraper):
    domain = 'bbc'

    def __init__(self, url):
        self.url = url

    def scrape_feed(self):
        with requests.get(self.url) as rep:
            # FIXME Better way than this atleast :P
            if rep:
                return bbc().scrape_feed(rep=rep)

    def scrape_product(self):
        with requests.get(self.url) as rep:
            # FIXME Better way than this atleast :P
            if rep:
                return bbc().scrape_product(rep=rep)

sydsvenskan.py

    from __future__ import annotations
    
    from selectolax.parser import HTMLParser
  
    
    @attr.dataclass
    class Info:
      """Scraped info about product"""
      all_articles: set = attr.ib(factory=set)
      store: str = attr.ib(factory=str)
      name: Optional[str] = attr.ib(factory=str)
      image: Optional[str] = attr.ib(factory=str)

    class sydsvenskan():
        def scrape_feed(self, rep):
            doc = HTMLParser(rep.text)
    
            all_products = {
                f"https://www.sydsvenskan.se{product_link.attrs['href']}" for product_link in
                doc.css('td.search-articles > a, div.product-image > a')
            }
    
            return Info(
                store="sydsvenskan",
                all_products=all_products
            )
    
        def scrape_article(self, rep):
            doc = HTMLParser(rep.text)
    
            name = "Test"
            price = "Test"
            image = "Test"
    
            return Info(
                store="Sydsvenskan",
                name=name,
                price=price,
                image=image,
            )

但是我的问题是我不知道是否最好添加我将来将监控的所有商店的静态导入(最多可以是 40 家新闻公司),或者是否最好只使用动态导入导入我们从参数调用的那个。 (如果我使用动态导入,我确实相信这个问题,当我们使用来自class Info 的数据类时,我无法从 pycharm 获得帮助,例如xxxx.pricexxxx.name 等)

所以我的问题是,什么对我更好。要将所有商店作为静态导入还是将动态导入到我的案例中?

【问题讨论】:

    标签: python python-3.x import


    【解决方案1】:

    性能问题的通用答案是:衡量然后决定。

    你问了两个问题。

    使用动态导入会更快吗?

    我会这么认为,但以非常微不足道的方式。除非运行此代码的计算机非常受限,否则差异将几乎不明显(启动时大约

    您可以通过将 sydsvenskan.py 文件复制 40 次,将它们中的每一个导入您的 scraper.py 并在前后运行 time python scraper.py 来快速测试它。

    一般来说,更喜欢做简单的事情。静态导入比动态导入更简单。

    即使导入是动态的,PyCharm 是否仍能提供代码洞察力?

    简单地说:是的。我测试了把它放在一个函数中,它工作得很好:

    # file: bbc_scraper.py
    class BBCScraper:
        def scrape(self) -> str:
            return "bar"
    
    # file: main.py
    def run_scraper_for_bbc():
        import bbc_scraper
        scraper = bbc_scraper.BBCScraper()
        print(scraper.scrape())
    

    【讨论】:

    • 非常感谢您为我这几天一直在寻找的问题提供了答案! :)
    猜你喜欢
    • 2011-04-14
    • 2011-01-06
    • 2023-03-16
    • 1970-01-01
    • 2016-12-31
    • 2022-09-30
    • 1970-01-01
    • 1970-01-01
    • 2020-02-25
    相关资源
    最近更新 更多