os.getxattr

Linux only - these functions and constants do not exist on Windows or macOS. Names carry a namespace prefix (unprivileged code uses 'user.'), values are bytes up to XATTR_SIZE_MAX (64 KiB on Linux), and the filesystem must support them.

os functionPython 3.3+
Common call
os.setxattr(path, 'user.tag', b'blue')
Returns
os.getxattr(path, 'user.tag') → b'blue'
Replaces
getfattr / setfattr command-line calls
Watch out
Values must be bytes; names need a namespace like 'user.'
os.getxattr(pathpath — The file (or an open file descriptor). listxattr: None examines the current directory.type: str | bytes | PathLike | int · required, attributeattribute — Attribute name including its namespace, e.g. 'user.tag'. str is encoded with the filesystem encoding.type: str | bytes | PathLike · required, *, follow_symlinksfollow_symlinks — False reads/writes the attributes of a symlink itself.type: bool · default: True=True)
→ bytes | list[str] | None

Parameters

NameTypeRequiredDescription
pathstr | bytes | PathLike | intyesThe file (or an open file descriptor). listxattr: None examines the current directory.
attributestr | bytes | PathLikeyesAttribute name including its namespace, e.g. 'user.tag'. str is encoded with the filesystem encoding.
valuebytes-likeyessetxattr: the new value; a str raises TypeError.
flagsintno (0)setxattr: 0 (create or replace), XATTR_CREATE (must not exist yet) or XATTR_REPLACE (must already exist).
follow_symlinksboolno (True)False reads/writes the attributes of a symlink itself.

Return value

bytes | list[str] | None — getxattr returns the value as bytes, listxattr a list of attribute names as str; setxattr and removexattr return None.

Common patterns

Tag a file (Linux)
Store, read back, list and remove a user attribute.
import os
os.setxattr('photo.jpg', 'user.rating', b'5')
os.getxattr('photo.jpg', 'user.rating')   # b'5'
os.listxattr('photo.jpg')                   # ['user.rating']
os.removexattr('photo.jpg', 'user.rating')
Create only if absent
XATTR_CREATE raises FileExistsError instead of overwriting.
import os
try:
    os.setxattr(path, 'user.origin', b'import', os.XATTR_CREATE)
except FileExistsError:
    pass
Optional metadata, portable
Fall back cleanly where xattrs do not exist, are not supported, or are absent.
import os
def get_tag(path):
    if not hasattr(os, 'getxattr'):
        return None
    try:
        return os.getxattr(path, 'user.tag').decode()
    except OSError:
        return None

Examples

1. A guarded reader works everywhere
import os def get_tag(path): if not hasattr(os, 'getxattr'): return None try: return os.getxattr(path, 'user.tag') except OSError: return None open('f.txt', 'w').close() get_tag('f.txt') is None
Returns
True
2. Names have a namespace
'user.comment'.partition('.')
Returns
('user', '.', 'comment')
3. str names become bytes
import os os.fsencode('user.tag')
Returns
b'user.tag'
4. Values are bytes
import json value = json.dumps({'rating': 5}).encode() (value, len(value) <= 65536)
Returns
(b'{"rating": 5}', True)
5. What XATTR_CREATE raises
import errno type(OSError(errno.EEXIST, 'File exists')).__name__
Returns
'FileExistsError'

Pitfalls

1. Forgetting the namespace
A bare name such as 'tag' is rejected by Linux (OSError, errno EOPNOTSUPP). Ordinary users can only write the 'user.' namespace.
'tag'
name = 'tag'
name.split('.', 1)[0] in ('user', 'trusted', 'security', 'system')
False
'user.tag'
name = 'user.tag'
name.split('.', 1)[0] in ('user', 'trusted', 'security', 'system')
True
2. Storing a value larger than the limit
On Linux a value over XATTR_SIZE_MAX (65536 bytes) fails with OSError (errno E2BIG). Check the size, or store a reference instead.
70000 bytes
value = b'x' * 70000
len(value) <= 65536
False
small value
import hashlib
value = hashlib.sha256(b'x' * 70000).hexdigest().encode()
len(value) <= 65536
True

When to use

Use it
  • Small per-file metadata on Linux: tags, checksums, origin markers
  • Reading security labels and ACL data (the security.* and system.* namespaces)
Reach for something else
  • Portable metadata → a sidecar file or a database
  • Data that must survive copies to other filesystems, zip files or cloud storage - attributes are often dropped
  • macOS extended attributes → not exposed by os (third-party packages)

Notes

CPython impl
getxattr/lgetxattr/fgetxattr and the matching set/list/remove calls in Modules/posixmodule.c, chosen by follow_symlinks and whether path is an fd
Availability
Linux only (the docs: "These functions are all available on Linux only"), added in 3.3. None of these names exist on Windows (verified)
Values
XATTR_CREATE = 1, XATTR_REPLACE = 2, XATTR_SIZE_MAX = 65536 (CPython 3.12 on Linux)
Errors (Linux)
getxattr of a missing name and setxattr with XATTR_REPLACE on a missing name: OSError errno 61 (ENODATA). XATTR_CREATE on an existing name: FileExistsError. Name without namespace: OSError errno 95. Value over 64 KiB: OSError errno 7 (verified on an ext4-type filesystem)

FAQ

The extended-attribute functions are Linux only - Windows and macOS builds of Python do not define them. The examples therefore show the naming and value rules and a hasattr-guarded reader instead of calling them.