从线程中删除重复的行
Posted
技术标签:
【中文标题】从线程中删除重复的行【英文标题】:Remove duplicate lines from threading 【发布时间】:2022-01-14 14:44:33 【问题描述】:我有一个程序从文件中随机读取行,并使用线程。问题是每当它从文件中读取行时,它有时会从文件中读取重复的行。例如,假设我使用 5 个线程,我的文件如下所示:
line1
line2
line3
line4
line5
程序使用线程随机读取行,但有时它可以读取 line4、line3、line5、line2、line5(再次)。所以我的问题是如何摆脱第 5 行重复?
代码:
def get_token():
tokens = []
with open('pokens.txt', 'r', encoding='UTF-8') as file:
lines = file.readlines()
for line in lines:
tokens.append(line.replace('\n', ''))
return tokens
def get_proxy():
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):
options = webdriver.ChromeOptions()
options.add_experimental_option("excludeSwitches", ["enable-logging"])
proxy_ip_port = proxy
proxy2 = Proxy()
proxy2.proxy_type = ProxyType.MANUAL
proxy2.http_proxy = proxy_ip_port
proxy2.ssl_proxy = proxy_ip_port
capabilities = webdriver.DesiredCapabilities.CHROME
proxy2.add_to_capabilities(capabilities)
self.browser = webdriver.Chrome("chromedriver.exe")
self.token = token
self.proxy = proxy
self.password = 'passwordhere'
def register(self):
print('hi')
# Code continues with no duplicates
def worker(proxy=None):
token_list = get_token()
token = random.choice(token_list)
d = Gen(token, proxy=proxy)
d.register()
def main():
threads = []
num_thread = input('Number of Threads: ')
num_thread = int(num_thread)
proxies = get_proxy()
for i in range(num_thread):
t = threading.Thread(target=worker, args= (random.choice(proxies), ))
threads.append(t)
t.start()
if __name__ == '__main__':
main()
【问题讨论】:
一个简单的解决方法(对于单线程或多线程实现)是提前生成一个从 1 到 N 的整数列表,然后随机化列表的顺序,然后给每个工作人员一个不同的部分并告诉工作人员在您提供的子列表中指定的行号处打印出行。 @JeremyFriesner 我不明白那个答案,你能给我一个代码示例之类的吗?我真的迷路了 【参考方案1】:以下是您的程序的简化“玩具版”,我对其进行了更新以执行以下操作:
-
将令牌文件从主线程读取到列表中
随机打乱列表的顺序
为每个工作人员提供一个大小大致相等的令牌列表子集供其选择
每个工作人员仅打印出由主线程提供的数据(为清楚起见,实际上省略了对数据执行的任何操作)
这种方法避免了重复,因为任何给定的标记只在列表中出现一次,并且每个线程都被赋予了列表的不同子集以从中选择标记。
import threading
import random
def read_tokens_list():
tokens = []
with open('pokens.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
def worker(proxy,token_list):
token = random.choice(token_list)
print("Worker: my proxy is [%s], my token list is %s, I've chosen [%s] as my token" % (proxy, token_list, token))
def main():
threads = []
num_thread = input('Number of Threads: ')
num_thread = int(num_thread)
proxies = read_proxies_list()
token_list = read_tokens_list() # read in the pokens.txt file
random.shuffle(token_list) # shuffle the list into random order
tokens_per_worker = len(token_list) // num_thread # how many tokens from the list each worker will get (roughly)
for i in range(num_thread):
if ((i+1)<num_thread):
num_tokens_for_this_worker = tokens_per_worker # give each worker an even share of the list
else:
num_tokens_for_this_worker = len(token_list) # except the last worker gets whatever is left
# we'll give the first (num_tokens_for_this_worker) tokens in the list to this worker
tokens_for_this_worker = token_list[0:num_tokens_for_this_worker]
# and remove those tokens from the list so that they won't get used by anyone else
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()
for t in threads:
t.join()
if __name__ == '__main__':
main()
【讨论】:
谢谢,这有效,但我还有一个问题。如果我想从原始 pokens.txt 文件中删除选择的令牌,我该怎么做?起初我虽然可以在没有令牌的情况下重写文件,但我认为这会破坏线程对吗? @Jarvn 您需要重写文件(就地更新文件在技术上是可行的,但通常不值得额外的复杂性,因为无论如何您最终都必须重写大部分文件)。您是正确的,尝试从多个线程写入文件会有问题;您只需从主线程执行该操作即可避免这种情况。 目前代码只运行一次,但如果我想在循环中运行代码并打印 tokens.txt 中的所有行,我该怎么做? 插入for循环或while循环,将要多次运行的代码移入其中,并在read_proxies_list()
中添加print()语句
我试过了,但是它不使用线程,只是在循环中运行一次代码以上是关于从线程中删除重复的行的主要内容,如果未能解决你的问题,请参考以下文章