#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. Да, я хочу, чтобы это продолжалось до тех пор, пока он не использует весь «токен» в файле.