Python: Циклическое выполнение кода с потоковой передачей

#python #python-3.x #multithreading #line #python-multithreading

#питон #python-3.x #многопоточность #линия #python-многопоточность

Вопрос:

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

Это и есть код:

 num_thread = input('Number of Threads: ') num_thread = int(num_thread)  def read_tokens_list():  tokens = []  with open('inputTokens.txt', 'r', encoding='UTF-8') as file:  lines = file.readlines()  for line in lines:  tokens.append(line.replace('n', ''))  return tokens  def read_proxies_list():  proxies = []  with open('proxies.txt', 'r', encoding='UTF-8') as file:  lines = file.readlines()  for line in lines:  proxies.append(line.replace('n', ''))  return proxies  class Gen:  def __init__(self, token, proxy=None):  self.token = token  self.proxy = proxy   def register(self):  print(f'Token: {self.token}')  print(f'Proxy: {self.proxy}') def worker(proxy, token_list):  token = random.choice(token_list)   d = Gen(token, proxy=proxy)  d.register()  def main():  threads = []   proxies = read_proxies_list()   token_list = read_tokens_list()  random.shuffle(token_list)  tokens_per_worker = len(token_list) // num_thread   for i in range(num_thread):  if ((i 1)lt;num_thread):  num_tokens_for_this_worker = tokens_per_worker  else:  num_tokens_for_this_worker = len(token_list)   tokens_for_this_worker = token_list[0:num_tokens_for_this_worker]   token_list = token_list[num_tokens_for_this_worker:]   t = threading.Thread(target=worker, args=(random.choice(proxies), tokens_for_this_worker, ))  threads.append(t)  t.start() if __name__ == '__main__':  main()  

Ответ №1:

У вас там много кода, который на самом деле ничего не делает.

Немного переписав его:

 import random import threading  num_threads = int(input('Number of threads:'))   def read_list(fn):  with open(fn, 'r') as f:  return [line.strip('n') for line in f]   class Gen:  def __init__(self, token, proxy=None):  self.token = token  self.proxy = proxy   def register(self):  print(f'Token: {self.token}')  print(f'Proxy: {self.proxy}')   def worker(proxy, token_list):  # why pick a random one from an already randomly ordered list? "more random"?  token = random.choice(token_list)   d = Gen(token, proxy=proxy)  d.register()   def main():  threads = []   proxies = read_list('proxies.txt')  tokens = read_list('tokens.txt')  random.shuffle(tokens)  tokens_per_worker = len(tokens) // num_threads   for i in range(num_threads):  # after looking at the complexity here, it looks like you just  # want to select an equal allotment of 'tokens' for each worker?  tokens_for_worker, tokens = tokens[:tokens_per_worker], tokens [tokens_per_worker:]  # why pick the 'proxy' at random here, but the 'token' in the worker?  t = threading.Thread(target=worker, args=(random.choice(proxies), tokens_for_worker,))  threads.append(t)  t.start()   if __name__ == '__main__':  main()  

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

В чем именно здесь проблема? Вывод:

 Number of threads:3 Token: t5 Proxy: p6 Token: t3 Proxy: p1 Token: t0 Proxy: p1  

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

На самом деле это имеет очень мало общего с многопоточностью. Ваша программа без потоковой передачи, ввода-вывода файлов или смешанных классов (которые были там без видимой цели):

 import random  # skip the input stuff num_threads = 2   def do_something(p, ts):  t = random.choice(ts)   print(f'Token: {t}')  print(f'Proxy: {p}')   # skip the file stuff, just some data proxies = [1, 2, 3] tokens = ['a', 'b', 'c', 'd', 'e']  tokens_per_worker = len(tokens) // num_threads  for i in range(2):  tokens_for_worker, tokens = tokens[:tokens_per_worker], tokens[tokens_per_worker:]  # skip the threads stuff  do_something(random.choice(proxies), tokens_for_worker)  

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

Итак, версия той же программы, которая делает то, что вы, кажется, хотите, чтобы она делала:

 import random  num_threads = 2   def do_something(p, ts):  t = random.choice(ts)   print(f'Token: {t}')  print(f'Proxy: {p}')   proxies = [1, 2, 3] tokens = ['a', 'b', 'c', 'd', 'e']  # only need to randomize once for tokens random.shuffle(tokens)  # since tokens is randomly sorted, we can now just use them one at a time in order for t in tokens:  do_something(random.choice(proxies), t)  

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

Комментарии:

1. Так, например, если я ввожу 2 потока и у меня в файле 20 строк, я хочу, чтобы программа печатала все 20 строк по 2 за раз, если это имеет смысл?

2. Ваш код и это делает именно это, так что нет — я не понимаю, чего вы пытаетесь достичь, чтобы ваш код или тот же код со всеми дополнительными функциями уже делал? Если только вы не чувствуете, что это печатает недостаточно строк — но это потому, что он использует ту же самую процедуру для перемешивания ваших исходных данных, для которой, похоже, нет никакой реальной цели (кроме случайной печати некоторых).

3. Так же, как я ввожу 2 потока, всякий раз, когда он заканчивает 2 потока, он продолжает коды до тех пор, пока все они не пройдут через все строки в файле. Проще всего объяснить, что всякий раз, когда я вводлю потоки, я хочу прокручивать код и не останавливаться всякий раз, когда код заканчивается.

4. Вы хотите сказать, что хотите, чтобы это продолжалось до тех пор, пока не будут использованы все «токены» и «прокси» в файлах? Но ваш код явно отбрасывает их — пожалуйста, четко объясните, что вам нужно. Возможно, приведите в своем вопросе простой пример, показывающий как входные данные (содержимое двух файлов примеров), так и ожидаемые выходные данные.

5. Да, я хочу, чтобы это продолжалось до тех пор, пока он не использует весь «токен» в файле.