Keywords: Python | File Permissions | Octal Notation
Abstract: This article provides an in-depth analysis of file permission anomalies in Python's os.chmod function, explaining why 664 and 0664 produce different permission outcomes. Through comparative analysis of octal and decimal conversions, it details the correct representation of permission values and offers compatibility solutions for Python 2 and Python 3. The discussion covers fundamental permission bit concepts and practical application scenarios to help developers avoid common permission setting errors.
Problem Phenomenon and Analysis
When using Python's os module for file permission configuration, many developers encounter a puzzling phenomenon: executing os.chmod("/tmp/test_file", 664) does not yield the expected rw-rw-r-- permissions, but instead results in -w--wx--- (corresponding to numerical value 230). However, when the parameter is changed to 0664, the permission setting works exactly as intended.
Core Role of Octal Notation
The root cause of this issue lies in Python's parsing rules for numeric literals. In Python, any integer starting with 0 is automatically interpreted as an octal number. Therefore, 664 is treated as decimal 664, while 0664 is correctly recognized as octal 664.
In Unix/Linux file systems, permission bits use octal notation:
- Read permission (r) corresponds to value 4
- Write permission (w) corresponds to value 2
- Execute permission (x) corresponds to value 1
Permissions are divided into three groups: owner, group, and others, with each group's permission being the sum of three bits. For example, rw-rw-r-- corresponds to octal calculation:
- Owner: 4 (read) + 2 (write) = 6
- Group: 4 (read) + 2 (write) = 6
- Others: 4 (read) = 4
Thus the correct octal representation is 664.
Mathematical Principles of Numerical Conversion
When passing 664 (decimal) to os.chmod, Python converts it to octal:
664 (decimal) = 1230 (octal)
Octal 1230 corresponds to permission bits:
- Owner: 2 (write)
- Group: 3 (write + execute)
- Others: 0 (no permissions)
This exactly matches the observed -w--wx--- permission pattern.
To achieve rw-rw-r-- permissions using decimal values, the calculation is:
664 (octal) = 436 (decimal)
Therefore, os.chmod("/tmp/test_file", 436) also produces the same result.
Python Version Compatibility Solutions
In Python 2, using octal prefix notation is recommended:
os.chmod("/tmp/test_file", 0664)
For Python 3, octal notation changes to 0o prefix:
os.chmod("/tmp/test_file", 0o664)
This change aligns with consistency improvements in Python 3's numeric literal syntax.
Practical Application Recommendations
For code readability and cross-version compatibility, we recommend:
- Always use octal notation to explicitly indicate permission intent
- Use
0prefix in Python 2 - Use
0oprefix in Python 3 - For code requiring multi-version compatibility, use conditional checks:
import sys
if sys.version_info >= (3, 0):
os.chmod(file_path, 0o664)
else:
os.chmod(file_path, 0664)
Understanding the principles of octal representation for file permissions not only ensures correct usage of os.chmod but also deepens comprehension of Unix/Linux file system permission models, preventing confusion between shell commands and programming interfaces.