EOFError: Ran out of input / EOF when reading a line (tested)
Python raises EOFError when it needs more data and the input has ended. The two messages people hit are EOFError: Ran out of input from pickle.load and EOFError: EOF when reading a line from input(). We measured both on Python 3.13.5.
1. pickle.load: EOFError: Ran out of input
import pickle, os
open("empty.pkl", "wb").close() # 0-byte file (crashed writer, touch, etc.)
try:
with open("empty.pkl", "rb") as f:
pickle.load(f)
except EOFError as e:
print("empty file:", type(e).__name__, e)
with open("one.pkl", "wb") as f:
pickle.dump({"a": 1}, f)
with open("one.pkl", "rb") as f:
print("first load:", pickle.load(f))
try:
pickle.load(f) # reading past the last object
except EOFError as e:
print("second load:", type(e).__name__, e)
data = pickle.dumps(list(range(1000)))
with open("cut.pkl", "wb") as f:
f.write(data[:len(data)//2]) # truncated write
try:
with open("cut.pkl", "rb") as f:
pickle.load(f)
except Exception as e:
print("truncated:", type(e).__name__, e)
Output:
empty file: EOFError Ran out of input
first load: {'a': 1}
second load: EOFError Ran out of input
truncated: UnpicklingError pickle data was truncated
Measured on Python 3.13.5: "Ran out of input" means pickle.load hit end of file before the first byte of an object. Two causes: the file is empty (0 bytes), or you already read the last object and called load again. A file cut off mid-object gives a different error, UnpicklingError: pickle data was truncated.
2. Why the file is empty
import pickle
f = open("data.pkl", "wb")
pickle.dump([1, 2, 3], f)
# forgot f.close() / flush: another reader opens it now
with open("data.pkl", "rb") as g:
try:
print(pickle.load(g))
except EOFError as e:
print("before close:", type(e).__name__, e)
f.close()
with open("data.pkl", "rb") as g:
print("after close:", pickle.load(g))
# opening for writing truncates first, so "w" then read in the same script = empty
open("data.pkl", "wb")
with open("data.pkl", "rb") as g:
try:
pickle.load(g)
except EOFError as e:
print("after open('wb'):", e)
Output:
before close: EOFError Ran out of input
after close: [1, 2, 3]
after open('wb'): Ran out of input
Measured: pickle.dump writes into Python's buffer; until the file is closed or flushed, a reader sees 0 bytes. Also, open(path, "wb") truncates the file immediately, so opening for write "just to check", or a crash between that open and the dump, leaves an empty file behind. Use with open(...) so the file is closed, and write to a temp file then os.replace() it if a crash mid-write matters.
3. Fixes: load every object, or default on empty
import pickle, os
def load_all(path):
out = []
with open(path, "rb") as f:
while True:
try:
out.append(pickle.load(f))
except EOFError:
return out
def load_or_default(path, default):
if not os.path.exists(path) or os.path.getsize(path) == 0:
return default
with open(path, "rb") as f:
return pickle.load(f)
with open("many.pkl", "wb") as f:
for i in range(3):
pickle.dump({"n": i}, f)
print(load_all("many.pkl"))
open("empty.pkl", "wb").close()
print(load_or_default("empty.pkl", {}))
print(load_or_default("missing.pkl", []))
Output:
[{'n': 0}, {'n': 1}, {'n': 2}]
{}
[]
To read a file you appended several dumps to, loop until EOFError; that's the documented end-of-stream signal. For a cache file that may be empty or missing, check the size first and fall back to a default rather than catching every EOFError (which would also hide a corrupt file you'd want to know about).
4. input(): EOFError: EOF when reading a line
name = input("name? ")
print("hello", name)
Run with and without stdin:
$ python3 b4.py < /dev/null
EOFError: EOF when reading a line
$ echo Ada | python3 b4.py
name? hello Ada
Measured: input() raises EOFError: EOF when reading a line when stdin has no more data: run with < /dev/null, piped from a command that printed nothing, Ctrl-D (Ctrl-Z Enter on Windows), a CI job, docker run without -i, or an editor "Run" panel that doesn't attach a console. Some online IDEs need you to type input into a separate stdin box before running.
5. Handling missing input
import sys
try:
line = input("name? ")
except EOFError:
line = "" # no stdin: Ctrl-D, closed pipe, CI, Docker without -i
print("got:", repr(line))
for line in sys.stdin: # reading every line: loop ends cleanly at EOF
print("line:", line.rstrip("\n"))
Run with and without stdin:
$ python3 b5.py < /dev/null
name? got: ''
$ printf "Ada\nx\ny\n" | python3 b5.py
name? got: 'Ada'
line: x
line: y
Catch EOFError around input() and use a default, or read with for line in sys.stdin, which just stops at end of input. For scripts that run unattended, take values from command-line arguments (argparse) or environment variables instead of prompting.
Frequently asked questions
What does EOFError: Ran out of input mean in pickle?
pickle.load reached end of file before any object started. We measured it for a 0-byte file and for calling load again after the last object. A file cut mid-object raises UnpicklingError: pickle data was truncated instead.
Why is my pickle file empty?
Usually the writer hadn't closed or flushed it yet (we measured 0 bytes visible before close), or open(path, 'wb') truncated it and the dump never ran. Use with open() and write to a temp file then os.replace().
How do I read multiple objects from one pickle file?
Call pickle.load in a loop and stop on EOFError. We measured three appended dumps loading back as a list of three.
What does EOFError: EOF when reading a line mean?
input() found no more data on stdin. We measured it with stdin from /dev/null; it also happens with Ctrl-D, CI jobs, docker without -i, and IDE run panels without a console.
How do I fix EOFError with input()?
Wrap input() in try/except EOFError with a default, read via for line in sys.stdin, or take arguments with argparse. Make sure the program actually has stdin attached.
Written with AI assistance. Measured on 2026-10-09 with Python 3.13.5 on Linux: pickle.load on an empty file, after the last object, on a truncated file and on an unflushed file; input() with stdin from /dev/null and from a pipe. Every block was run verbatim and its output pasted from that run. Windows consoles and IDE run panels were not tested. PlainHeaders is our extension; everything else here is built-in Python.