hankcs/HanLP · error · ValueError
Expected a file (`.fileno()`) or a file descriptor
Error message
Expected a file (`.fileno()`) or a file descriptor
What it means
fileno() normalizes files and file descriptors for stdout redirection; after calling .fileno() on the object, the result must be an int fd. If the object exposes a fileno() that returns something else (or a non-file, non-int object sneaks through), it raises ValueError.
Source
Thrown at hanlp/utils/io_util.py:539
if r[2 * sid] <= ratio < r[2 * sid + 1]:
if isinstance(sample, list):
sample = '\n'.join('\t'.join(x) for x in sample) + '\n\n'
out.write(sample)
break
if not filepath.endswith('.tsv'):
src.close()
for out in outs:
out.close()
return filenames
def fileno(file_or_fd):
try:
fd = getattr(file_or_fd, 'fileno', lambda: file_or_fd)()
except:
return None
if not isinstance(fd, int):
raise ValueError("Expected a file (`.fileno()`) or a file descriptor")
return fd
@contextmanager
def stdout_redirected(to=os.devnull, stdout=None):
"""Redirect stdout to else where.
Copied from https://stackoverflow.com/questions/4675728/redirect-stdout-to-a-file-in-python/22434262#22434262
Args:
to: Target device.
stdout: Source device.
"""
if windows(): # This doesn't play well with windows
yield None
return
if stdout is None:
stdout = sys.stdoutView on GitHub (pinned to ddb1299bdd)
Solutions
- Pass a real file object or an integer fd to stdout_redirected.
- For in-memory capture, create a real temp file (open(tempfile.mkstemp()[1])) or use contextlib.redirect_stdout instead.
- If wrapping, ensure your wrapper's fileno() delegates to the underlying file's fileno.
Example fix
# before with stdout_redirected(io.StringIO()): ... # after import tempfile, os fd, tmp = tempfile.mkstemp() with stdout_redirected(os.fdopen(fd, 'w')): ... os.remove(tmp)
Defensive patterns
Strategy: type-guard
Validate before calling
fd = getattr(f, 'fileno', lambda: f)() assert isinstance(fd, int) and fd >= 0, 'need a real file or fd'
Type guard
def is_real_file(f):
fd = getattr(f, 'fileno', lambda: None)()
return isinstance(fd, int) and fd >= 0 Prevention
- Use contextlib.redirect_stdout for in-memory capture.
- Always pass open() file objects or ints into redirection helpers.
When it happens
Trigger: Passing an object to fileno()/stdout_redirected/_get_file_size whose fileno() returns a non-int (e.g. a mock, io.StringIO in some wrappers returning None, or an object whose __getattr__ yields junk).
Common situations: Redirecting stdout to a StringIO/captured buffer in tests; substituting fake file objects; Python 2/3 differences in file-like wrappers.
AI-assisted analysis of hankcs/HanLP@ddb1299bdd (2026-08-27).
Data as JSON: /api/errors/db705d8bd5a3b6df.
Report an issue: GitHub.