Не удается настроить многопроцессорность для работы с экземплярами моего класса в Python - PullRequest
0 голосов
/ 27 апреля 2020

В основном я хочу создать несколько экземпляров одного и того же объекта и выполнить их отдельно в одно и то же время. Пример кода для этого:

class Student:

    def __init__(self, username_, password_):
        self.username = username_
        self.password = password_
        self.driver = webdriver.Chrome('chromedriver.exe')

    def login(self):
        # Go to students page
        self.driver.get('https://www.students.com/')
        time.sleep(2)

        # Enter username in login form
        enter_username = WebDriverWait(self.driver, 20).until(
            expected_conditions.presence_of_element_located((By.NAME, 'username')))
        enter_username.send_keys(self.username)
        # Enter password in login form
        enter_password = WebDriverWait(self.driver, 20).until(
            expected_conditions.presence_of_element_located((By.NAME, 'password')))
        enter_password.send_keys(self.password)

        # Wait to send the form
        time.sleep(2)

        # Click Log In button
        self.driver.find_elements_by_xpath("//div[contains(text(), 'Iniciar sesión')]")[0].click()

        # Wait for the form to be sent
        time.sleep(5)
        self.start_working()
        # This functions is and endless loop that simulates work

if __name__ == '__main__':
            load_dotenv()

            query = "SELECT username, password FROM students"
            cursor.execute(query)
            records = cursor.fetchall()

            print("Total number of accounts botting up ", cursor.rowcount)

            object_list = list()
            for username, password in records:
                obj = Student(username, password)
                object_list.append(obj)

            instance_list = list()
            for x in object_list:
                p = multiprocessing.Process(target=x.login)
                p.start()
                instace_list.append(p)

            for x in instance_list:
                x.join()

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

Я получаю эту ошибку в терминале:

 (student-bot) C:\python\student-bot>Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "c:\users\alberto\appdata\local\programs\python\python37\lib\multiprocessing\spawn.py", line 99, in spawn_main
    new_handle = reduction.steal_handle(parent_pid, pipe_handle)
  File "c:\users\alberto\appdata\local\programs\python\python37\lib\multiprocessing\reduction.py", line 87, in steal_handle
    _winapi.DUPLICATE_SAME_ACCESS | _winapi.DUPLICATE_CLOSE_SOURCE)
PermissionError: [WinError 5] Acceso denegado
[13852:1860:0427/193022.541:ERROR:device_event_log_impl.cc(162)] [19:30:22.541] Bluetooth: bluetooth_adapter_winrt.cc:1055 Getting Default Adapter failed.


1 Ответ

0 голосов
/ 27 апреля 2020

Вы, вероятно, хотите target=x.login, а не x.login(). В противном случае вы будете звонить на все, что вернет target.login(), что может даже не вызываться. Один «исполняющий» процесс может фактически быть просто основным потоком и является результатом, который вы кодировали x.login(), но на самом деле ни один из подпроцессов не работает. Было бы полезно показать сообщения об ошибках. Также убедитесь, что приведенный выше код находится внутри блока, который начинается:

if __name__ == '__main__':

Например:

import multiprocessing

class Foo:
    def bar(self, i):
        print(i, flush=True)

f = Foo()

if __name__ == '__main__':
    instace_list = list()
    for i in range(3):
        p = multiprocessing.Process(target=f.bar, args=(i,))
        p.start()
        instace_list.append(p)

    for x in instace_list:
        x.join()

Отпечатки:

0
1
2

Обновление

В идеале ваш файл должен быть структурирован следующим образом:

import blah, blah, blah;

class Student: # or perhaps this is imported above
    # definition of this class

def foo():
    # definition of foo

def bar():
    #d definition of bar

def query_database():
        load_dotenv()
        # obtain connection and cursor (code not shown)
        query = "SELECT username, password FROM students"
        cursor.execute(query)
        records = cursor.fetchall()

        print("Total number of accounts botting up ", cursor.rowcount)

        object_list = list()
        for username, password in records:
            obj = Student(username, password)
            object_list.append(obj)

        return object_list

if __name__ == '__main__':
        object_list = query_database() # get Student list
        with multiprocessing.Pool(processes=8) as pool:
            instance_list = list()
            for x in object_list:
                result = pool.apply_async(x.login)
                instance_list.append(result)

            for result in instance_list:
                result.get() # return value from login, which is None

Обновление 2

Поскольку метод login не отображается в быть процесс, связанный с процессором, вы можете рассмотреть использование потоков. Этот код не обязательно должен находиться внутри блока __main__ (хотя это совершенно правильно сделать):

from concurrent.futures import ThreadPoolExecutor

object_list = query_database() # get Student list
with ThreadPoolExecutor(max_workers=8) as executor:
    instance_list = list()
    for x in object_list:
        future = executor.submit(x.login)
        instance_list.append(future)

    for future in instance_list:
        future.get() # return value from login, which is None
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...