Open a large file in Python without running out of RAM

Viewed 120

I'm trying to open a file with 5 million entries in Python

My code needs to fetch inputs line by line in order (a difference of a few tens of lines with ThreadPoolExecutor is not a problem) and then be fetched by ThreadPoolExecutor to send to get_url function

Maybe the url variable is getting too big, ThreadPoolExecutor should itself retrieve them one by one from the file by keeping a line counter? I already tried to do this but failed (this is the first time I use ThreadPoolExecutor)

with open("1_1.txt") as stream:
    urls = [line.strip() for line in stream]

with ThreadPoolExecutor(max_workers=50) as pool:
    pool.map(get_url, urls)

The full code of my script :

import requests
from concurrent.futures import ThreadPoolExecutor
import fileinput
from bs4 import BeautifulSoup
import traceback
from threading import Thread


from requests.packages.urllib3.exceptions import InsecureRequestWarning
import warnings

from random import random
from queue import Queue


requests.packages.urllib3.disable_warnings(InsecureRequestWarning)

warnings.filterwarnings("ignore", category=UserWarning, module='bs4')

count_requests = 0
host_error = 0


def get_url(url):
    global queue
    global count_requests
    global host_error

    try:
        

        result_request = requests.get(url, verify=False, timeout=40)
        soup = BeautifulSoup(result_request.text, 'html.parser')

        title = soup.title.get_text().splitlines(False)
        
        title = str(title)
        title = title[0:10000]


        count_requests = count_requests + 1
        
        queue.put(f'{url} - {title} \n')
        
      

      
    except:
        queue.put(f'FAILED : {url} \n')
        host_error = host_error + 1


# dedicated file writing task
def file_writer(filepath, queue):
    global count_requests
    # open the file
    with open(filepath, 'a', encoding="utf-8") as file:
        # run until the event is set
        while True:
            # get a line of text from the queue
            line = queue.get()
            # check if we are done
            if line is None:
                # exit the loop
                break
            # write it to file
            file.write(line)
            # flush the buffer
            file.flush()
            # mark the unit of work complete
            queue.task_done()
    # mark the exit signal as processed, after the file was closed
    queue.task_done()
    
    



# create the shared queue
queue = Queue()
# defile the shared file path
filepath = 'output.txt'
# create and start the file writer thread
writer_thread = Thread(target=file_writer, args=(filepath,queue), daemon=True)
writer_thread.start()



# wait for all tasks in the queue to be processed
queue.join()



with open("1_1.txt") as stream:
    urls = [line.strip() for line in stream]

with ThreadPoolExecutor(max_workers=1) as pool:
    pool.map(get_url, urls)
1 Answers

Try to do it with submit() method:

with open("1_1.txt") as stream:
    with ThreadPoolExecutor(max_workers=50) as pool:
        for url in stream:
            pool.submit(get_url,url.strip())
Related