Проблема с мультипроцессором в Python с BeautifulSoup 4 - PullRequest
0 голосов
/ 04 мая 2018

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

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

Я попробовал приведенный ниже код, но, похоже, не использовал все ядро.

Следующий код будет в основном получать файл * .txt в каталоге, который содержит htmls, в формате json.

   #!/usr/bin/python
    # -*- coding: utf-8 -*-
    import requests
    import json
    import urlparse
    import os
    from bs4 import BeautifulSoup
    from multiprocessing.dummy import Pool  # This is a thread-based Pool
    from multiprocessing import cpu_count

    def crawlTheHtml(htmlsource):
        htmlArray = json.loads(htmlsource)
        for eachHtml in htmlArray:
            soup = BeautifulSoup(eachHtml['result'], 'html.parser')
            if all(['another text to search' not in str(soup),
                   'text to search' not in str(soup)]):
                try:
                    gd_no = ''
                    try:
                        gd_no = soup.find('input', {'id': 'GD_NO'})['value']
                    except:
                        pass

                    r = requests.post('domain api address', data={
                        'gd_no': gd_no,
                        })
                except:
                    pass


    if __name__ == '__main__':
        pool = Pool(cpu_count() * 2)
        print(cpu_count())
        fileArray = []
        for filename in os.listdir(os.getcwd()):
            if filename.endswith('.txt'):
                fileArray.append(filename)
        for file in fileArray:
            with open(file, 'r') as myfile:
                htmlsource = myfile.read()
                results = pool.map(crawlTheHtml(htmlsource), f)

Кроме того, я не уверен, что, f представляют.

Вопрос 1:

Что я не сделал правильно, чтобы полностью использовать все ядра / потоки?

Вопрос 2:

Есть ли лучший способ использовать try: кроме: потому что иногда значение отсутствует на странице и это может привести к остановке скрипта. При работе с несколькими переменными я получу много операторов try & исключением.

Ответы [ 3 ]

0 голосов
/ 04 мая 2018

у меня была эта проблема вам нужно сделать

from multiprocessing import Pool
from multiprocessing import freeze_support

и нужно в итоге сделать

if __name__ = '__main__':
  freeze_support()

и вы можете продолжить свой сценарий

0 голосов
/ 05 мая 2018
from  multiprocessing import Pool, Queue
from os import getpid
from time import sleep
from random import random

MAX_WORKERS=10

class Testing_mp(object):
    def __init__(self):
        """
        Initiates a queue, a pool and a temporary buffer, used only
        when the queue is full.
        """
        self.q = Queue()
        self.pool = Pool(processes=MAX_WORKERS, initializer=self.worker_main,)
        self.temp_buffer = []

    def add_to_queue(self, msg):
        """
        If queue is full, put the message in a temporary buffer.
        If the queue is not full, adding the message to the queue.
        If the buffer is not empty and that the message queue is not full,
        putting back messages from the buffer to the queue.
        """
        if self.q.full():
            self.temp_buffer.append(msg)
        else:
            self.q.put(msg)
            if len(self.temp_buffer) > 0:
                add_to_queue(self.temp_buffer.pop())

    def write_to_queue(self):
        """
        This function writes some messages to the queue.
        """
        for i in range(50):
            self.add_to_queue("First item for loop %d" % i)
            # Not really needed, just to show that some elements can be added
            # to the queue whenever you want!
            sleep(random()*2)
            self.add_to_queue("Second item for loop %d" % i)
            # Not really needed, just to show that some elements can be added
            # to the queue whenever you want!
            sleep(random()*2)

    def worker_main(self):
        """
        Waits indefinitely for an item to be written in the queue.
        Finishes when the parent process terminates.
        """
        print "Process {0} started".format(getpid())
        while True:
            # If queue is not empty, pop the next element and do the work.
            # If queue is empty, wait indefinitly until an element get in the queue.
            item = self.q.get(block=True, timeout=None)
            print "{0} retrieved: {1}".format(getpid(), item)
            # simulate some random length operations
            sleep(random())

# Warning from Python documentation:
# Functionality within this package requires that the __main__ module be
# importable by the children. This means that some examples, such as the
# multiprocessing.Pool examples will not work in the interactive interpreter.
if __name__ == '__main__':
    mp_class = Testing_mp()
    mp_class.write_to_queue()
    # Waits a bit for the child processes to do some work
    # because when the parent exits, childs are terminated.
    sleep(5)
0 голосов
/ 04 мая 2018

Ответ на вопрос 1, ваша проблема в этой строке:

from multiprocessing.dummy import Pool  # This is a thread-based Pool

Ответ получен от: multiprocessing.dummy в Python не использует 100% CPU

Когда вы используете multiprocessing.dummy, вы используете потоки, а не процессы:

multiprocessing.dummy копирует API многопроцессорной обработки, но не больше, чем обертка вокруг резьбового модуля.

Это означает, что вы ограничены Global Interpreter Lock (GIL) , и только один поток может фактически выполнять операции с привязкой к ЦП одновременно. Это не позволит вам полностью использовать ваши процессоры. Если вы хотите получить полный параллелизм по всем доступным ядрам, вам нужно решить проблему травления, с которой вы сталкиваетесь multiprocessing.Pool.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...