从线程中删除重复的行

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()语句 我试过了,但是它不使用线程,只是在循环中运行一次代码

以上是关于从线程中删除重复的行的主要内容,如果未能解决你的问题,请参考以下文章

我如何从数据框中删除具有重复/重复索引的行[重复]

如何从文本文件中删除重复并包含某些单词的行?

如何从mysql中的表中删除重复的行

从 DataGrid 中删除重复的行

如何使用 SSIS 从平面文件中删除重复的行?

从 sqlite 数据库中删除重复的行