To expand upon my comments:
This implementation, according to psutil, takes about 26 megabytes of RSS memory total, with 10 megabytes having been allocated during read_file()
.
(As an added bonus, since we have the luxury of using a full byte of memory per integer, we can count exactly how many of each there was (unless we overflow the 8 bits...).)
import random
import array
import psutil
def read_file(inf):
n = int(inf.readline())
# Preallocate an array.
# TODO: this uses one byte per `n`, not one bit.
# The allocation also takes some additional temporary memory
# due to the list initializer.
arr = array.array("b", [0] * n)
input_buffer = ""
nr = 0
while True:
# Read a chunk of data,
read_buffer = inf.read(131072)
# Add it to the input-accumulating buffer
input_buffer += read_buffer
# Partition the accumulating buffer from the right,
# and swap the "rest" (after the last space) to be
# the new accumulating buffer.
process_chunk, sep, input_buffer = input_buffer.rpartition(" ")
if not process_chunk: # Nothing to process anymore
break
for value in process_chunk.split(" "):
arr[int(value)] += 1
nr += 1
assert n == nr
return arr
mi0 = psutil.Process().memory_info()
with open("output.txt", "r") as inf:
arr = read_file(inf)
mi1 = psutil.Process().memory_info()
print("initial memory usage", mi0.rss)
print("final memory usage..", mi1.rss)
print("delta from initial..", mi1.rss - mi0.rss)