The Story That Explains the os Module 🔑os Module समझाने वाली कहानी 🔑一个讲清 os 模块的故事 🔑
Python's
os module is that master key for your computer. It can show the current folder, list a folder's contents, create, rename and delete files and folders, walk through a whole folder tree, read environment variables and ask about the running program.You don't need
os for pure calculation — that is what math and collections are for. You need it the moment your program has to deal with the outside world: the file system, the settings it was started with, and the computer it is running on.Python का
os module आपके कंप्यूटर की वही master key है। यह मौजूदा folder दिखा सकता है, folder की सामग्री की सूची बना सकता है, files और folders बना, बदल और delete कर सकता है, पूरे folder tree में घूम सकता है, environment variables पढ़ सकता है और चल रहे program के बारे में पूछ सकता है।सिर्फ़ गणना के लिए
os की ज़रूरत नहीं — उसके लिए math और collections हैं। इसकी ज़रूरत तब पड़ती है जब आपके program को बाहरी दुनिया से निपटना हो: file system, जिन settings के साथ वह शुरू हुआ, और जिस कंप्यूटर पर वह चल रहा है।Python 的
os 模块 就是你电脑的万能钥匙。它能告诉你当前文件夹、列出文件夹内容、创建/重命名/删除文件和文件夹、遍历整个文件夹树、读取环境变量,并查询正在运行的程序。纯计算用不到
os — 那是 math 和 collections 的活。一旦程序要和 外部世界 打交道 — 文件系统、启动时的设置、所运行的电脑 — 你就需要它。The os module is Python's bridge to your operating system. Its star, os.walk(), visits every folder in a tree — the reason a ten-line script can tidy up thousands of files.
os module आपके operating system तक Python का पुल है। इसका सितारा, os.walk(), tree के हर folder में जाता है — इसी वजह से दस lines की script हज़ारों files सँभाल सकती है।
os 模块是 Python 通往操作系统的桥梁。它的明星 os.walk() 会访问树中的每个文件夹 — 这就是十行脚本能整理成千上万个文件的原因。
Your script talks to os; os talks to the operating system — whether that is Windows, macOS or Linux.
आपकी script os से बात करती है; os operating system से — चाहे वह Windows हो, macOS या Linux।
你的脚本和 os 对话;os 再和操作系统对话 — 无论是 Windows、macOS 还是 Linux。
Functions like os.mkdir, os.remove and os.listdir are thin wrappers around the operating system's own calls, so they work the same way on Windows, macOS and Linux. os.path is different: most of it (join, split, splitext) is pure text work that follows your system's path rules and never touches the disk. Only a few functions, like exists and getsize, actually look at real files.
os.mkdir, os.remove और os.listdir जैसे functions operating system की अपनी calls पर पतली परत हैं, इसलिए Windows, macOS और Linux पर एक जैसे चलते हैं। os.path अलग है: इसका ज़्यादातर हिस्सा (join, split, splitext) सिर्फ़ text का काम है जो आपके system के path नियम मानता है और disk को कभी नहीं छूता। सिर्फ़ कुछ functions, जैसे exists और getsize, असली files देखते हैं।
os.mkdir、os.remove、os.listdir 这类函数是对操作系统自身调用的薄封装,所以在 Windows、macOS 和 Linux 上用法一致。os.path 则不同:它的大部分(join、split、splitext)只是遵循系统路径规则的 文本 处理,从不访问磁盘。只有少数函数,如 exists 和 getsize,才会真正查看文件。
Look for the interactive boxes: the Folder Operations Story (Section 05), the Path Dissector (06), the os.walk Explorer (08) and the Environment Lab (10). Everything they show came from running real Python 3.13 on a real folder tree.
Interactive डिब्बे खोजें: Folder Operations Story (Section 05), Path Dissector (06), os.walk Explorer (08) और Environment Lab (10)। ये जो कुछ दिखाते हैं, वह असली folder tree पर असली Python 3.13 चलाकर आया है।
请留意这些互动框:文件夹操作故事(第 05 节)、路径解剖器(06)、os.walk 探索器(08)和 环境变量实验室(10)。它们显示的一切,都来自在真实文件夹树上运行真实的 Python 3.13。
The Six Families of os Functions 👪os Functions के छह परिवार 👪os 函数的六大家族 👪
The os module is large, but almost every function belongs to one of six families. Know the families and you will always know where to look.
os module बड़ा है, पर लगभग हर function छह परिवारों में से एक का है। परिवार जान लें तो हमेशा पता रहेगा कि कहाँ देखना है।
os 模块很大,但几乎每个函数都属于六大家族之一。认识这些家族,你就总能知道去哪里找。
getcwd, chdir, listdir, mkdir, makedirs, rmdir, removedirs — everything about the folders themselves.getcwd, chdir, listdir, mkdir, makedirs, rmdir, removedirs — ख़ुद folders से जुड़ा सब कुछ।getcwd、chdir、listdir、mkdir、makedirs、rmdir、removedirs — 一切与文件夹本身有关的操作。rename, replace, remove, stat. To read or write the contents, use open() or pathlib — os handles the file's life and details.rename, replace, remove, stat। सामग्री पढ़ने-लिखने के लिए open() या pathlib इस्तेमाल करें — os file के जीवन और जानकारी को संभालता है।rename、replace、remove、stat。读写文件 内容 请用 open() 或 pathlib — os 负责文件的生命周期和元数据。join, split, basename, dirname, splitext, exists. Text operations that follow your system's path rules.join, split, basename, dirname, splitext, exists। Text के काम जो आपके system के path नियम मानते हैं।join、split、basename、dirname、splitext、exists。遵循系统路径规则的文本操作。os.name, getpid, cpu_count, process_cpu_count. To run other programs, use the subprocess module.os.name, getpid, cpu_count, process_cpu_count। दूसरे programs चलाने के लिए subprocess module इस्तेमाल करें।os.name、getpid、cpu_count、process_cpu_count。运行其他程序请用 subprocess 模块。scandir lists one folder fast; walk goes all the way down. This is where the magic happens.scandir एक folder जल्दी दिखाता है; walk पूरे नीचे तक जाता है। जादू यहीं होता है।scandir 快速列出一个文件夹;walk 一路深入到底。魔法就在这里。Getting Oriented — Where Am I? 🧭दिशा पहचानना — मैं कहाँ हूँ? 🧭找准方位 — 我在哪里?🧭
All the examples in this tutorial run inside the same practice folder, which contains a small project/ tree, some photos, logs and loose files.
इस tutorial के सारे उदाहरण एक ही practice folder में चलते हैं, जिसमें एक छोटा project/ tree, कुछ photos, logs और खुली files हैं।
本教程所有示例都在同一个练习文件夹中运行,里面有一个小型 project/ 树、一些照片、日志和零散文件。
import os
# Where is my script running from?
print(os.getcwd())
# What is in this folder? (sorted, because the order is not guaranteed)
print(sorted(os.listdir()))
# List a DIFFERENT folder without moving
print(sorted(os.listdir("project")))
# Check before you touch
print(os.path.exists("data.csv"), os.path.isfile("data.csv"), os.path.isdir("data.csv"))
print(os.path.exists("missing.csv"))
print(os.path.isdir("project"))
exists(), isfile() and isdir() let you choose a path before something fails. But the disk can change between your check and your action, so for real programs it is often safer to just try the operation and catch the specific error (FileExistsError, FileNotFoundError…). Also note: listdir() returns names in no particular order — sort them when order matters.
exists(), isfile() और isdir() से आप कुछ fail होने से पहले रास्ता चुन सकते हैं। पर आपकी जाँच और काम के बीच disk बदल सकती है, इसलिए असली programs में अक्सर बेहतर है कि सीधे काम करें और ख़ास error पकड़ें (FileExistsError, FileNotFoundError…)। यह भी ध्यान दें: listdir() नाम किसी तय क्रम में नहीं देता — क्रम ज़रूरी हो तो sort करें।
exists()、isfile()、isdir() 让你在出错前选择路线。但在检查和操作之间磁盘可能发生变化,所以真实程序里往往直接执行操作并捕获具体错误(FileExistsError、FileNotFoundError……)更安全。另外注意:listdir() 返回的名字没有特定顺序 — 需要顺序时请排序。
Creating and Removing Folders 🏗️Folders बनाना और हटाना 🏗️创建与删除文件夹 🏗️
import os
import shutil
os.mkdir("reports") # ONE folder
os.makedirs("archive/2026/january/raw") # a whole chain at once
os.makedirs("cache", exist_ok=True) # no error if it already exists
os.makedirs("cache", exist_ok=True) # ...so running it twice is fine
for action in [lambda: os.mkdir("reports"), # already exists
lambda: os.mkdir("logs2/2026/jan"), # parent missing
lambda: os.rmdir("archive")]: # not empty
try:
action()
except OSError as e:
print(type(e).__name__, "->", e)
os.rmdir("reports") # empty -> removed
os.removedirs("archive/2026/january/raw") # removes the empty chain, bottom-up
print(os.path.exists("archive"))
open("cache/data.bin", "w").close()
shutil.rmtree("cache") # deletes a folder AND everything in it
print(os.path.exists("cache"))
shutil. Deletes a folder and everything inside it. No undo, no recycle bin.
shutil से। Folder और उसके अंदर का सब कुछ delete करता है। कोई undo नहीं, कोई recycle bin नहीं।
来自 shutil。删除文件夹及其中 一切。无法撤销,没有回收站。
File Operations — Rename, Remove, Inspect 📄File के काम — नाम बदलना, हटाना, जाँचना 📄文件操作 — 重命名、删除、查看 📄
import os
from datetime import datetime, timezone
# Rename and move use the same call
os.rename("draft.txt", "final.txt")
os.rename("final.txt", "reports_archive/final.txt") # into another folder
print(sorted(os.listdir("reports_archive")))
# Delete a file - permanent, no recycle bin
os.remove("temp.log")
print(os.path.exists("temp.log"))
# Metadata: size, timestamps, permissions
info = os.stat("data.csv")
print(f"Size: {info.st_size} bytes")
print(f"Modified: {info.st_mtime}") # seconds since 1 Jan 1970 (UTC)
print(f"Mode: {oct(info.st_mode)}")
when = datetime.fromtimestamp(info.st_mtime, tz=timezone.utc)
print(f"Readable: {when:%Y-%m-%d %H:%M} UTC")
st_mtime is a count of seconds since 1 January 1970 (UTC), often called a timestamp. Convert it with datetime.fromtimestamp(). The mode 0o100644 means "a regular file that the owner can read and write, and everyone else can read".
st_mtime 1 जनवरी 1970 (UTC) से बीते सेकंडों की गिनती है, जिसे अक्सर timestamp कहते हैं। इसे datetime.fromtimestamp() से बदलें। Mode 0o100644 का मतलब है "एक सामान्य file जिसे owner पढ़-लिख सकता है, और बाक़ी सब पढ़ सकते हैं"।
st_mtime 是自 1970 年 1 月 1 日(UTC)以来的秒数,通常叫 时间戳。用 datetime.fromtimestamp() 转换。模式 0o100644 表示"普通文件,所有者可读写,其他人只读"。
Try It — Folder Operations Storyकरके देखें — Folder Operations Story动手试试 — 文件夹操作故事
Three short stories, each a sequence of real calls run on a real empty folder. Step through and watch the tree change after every call — green rows appear, red rows disappear, and errors are shown exactly as Python reported them.
तीन छोटी कहानियाँ, हर एक असली ख़ाली folder पर चलाई गई असली calls का क्रम। कदम-दर-कदम चलें और हर call के बाद tree बदलते देखें — हरी rows आती हैं, लाल rows जाती हैं, और errors वैसे ही दिखते हैं जैसे Python ने बताए।
三个小故事,每个都是在真实空文件夹上运行的一系列真实调用。逐步执行,看每次调用后树的变化 — 绿色行出现,红色行消失,错误与 Python 报告的完全一致。
Path Anatomy — What Makes Up a Path 🧬Path की बनावट — Path किससे बनता है 🧬路径解剖 — 路径由什么组成 🧬
Every path can be split into named parts, and os.path has a function for each part.
हर path को नाम वाले हिस्सों में बाँटा जा सकता है, और os.path में हर हिस्से के लिए एक function है।
每个路径都能拆成有名字的部分,os.path 为每个部分都提供了函数。
/home/aarav/data/report.csv/home/aarav/data/report.csv का विच्छेदन解剖 /home/aarav/data/report.csvsplit() gives (dirname, basename) in one call; splitext() splits off the extension; join() puts the parts back together.
split() एक call में (dirname, basename) देता है; splitext() extension अलग करता है; join() हिस्सों को वापस जोड़ता है।
split() 一次给出 (dirname, basename);splitext() 拆出扩展名;join() 把各部分重新拼起来。
import os
path = "/home/aarav/data/report.csv"
print(os.path.basename(path))
print(os.path.dirname(path))
print(os.path.split(path)) # (dirname, basename)
print(os.path.splitext(path)) # (everything before the extension, extension)
print(os.path.join("/home/aarav", "reports", "2026", "jan.csv"))
print(os.path.isabs(path), os.path.isabs("data.csv"))
Four Path SurprisesPath के चार चौंकाने वाले नियम路径的四个意外
import os
import ntpath # the rules os.path uses on Windows, available everywhere
# 1) An absolute part throws away everything before it
print(os.path.join("data", "/etc/passwd"))
# 2) normpath tidies "..", "." and doubled slashes
print(os.path.normpath("data//2026/./jan/../feb/sales.csv"))
# 3) splitext only takes the LAST extension
print(os.path.splitext("backup.tar.gz"))
print(os.path.splitext(".bashrc")) # a leading dot is not an extension
# 4) The same join on Windows rules
print(ntpath.join("C:\\Users", "aarav", "notes.txt"))
print(ntpath.splitext("C:\\Users\\aarav\\report.CSV"))
Try It — Path Dissectorकरके देखें — Path Dissector动手试试 — 路径解剖器
Pick a path and a rule set. The coloured bar shows how Python splits it (folder · separator · name · extension), and the table shows the exact values Python returns. Try the Windows paths with Linux/macOS rules — a surprise awaits.
एक path और नियमों का सेट चुनें। रंगीन पट्टी दिखाती है कि Python उसे कैसे बाँटता है (folder · separator · नाम · extension), और table वही values दिखाती है जो Python लौटाता है। Windows paths को Linux/macOS नियमों से आज़माएँ — एक हैरानी इंतज़ार में है।
选择一个路径和一套规则。彩色条显示 Python 如何拆分它(文件夹 · 分隔符 · 名字 · 扩展名),表格显示 Python 返回的确切值。用 Linux/macOS 规则试试 Windows 路径 — 有惊喜等着你。
join, Not +Paths join से बनाएँ, + से नहीं用 join 而不是 + 构建路径"data/" + name mostly works — Windows accepts / in most places — but string gluing causes real bugs: doubled or missing slashes, Windows paths built with \ that break on Linux, and paths shown to users in the wrong style. os.path.join() (or pathlib's /) uses the right separator and handles the edge cases. Just remember surprise #1: a part that starts with / throws away everything before it.
"data/" + name ज़्यादातर चलता है — Windows ज़्यादातर जगह / स्वीकार करता है — पर strings जोड़ने से असली bugs होते हैं: दोहरे या ग़ायब slashes, \ से बने Windows paths जो Linux पर टूटते हैं, और users को ग़लत शैली में दिखते paths। os.path.join() (या pathlib का /) सही separator इस्तेमाल करता है और किनारे के मामले संभालता है। बस हैरानी #1 याद रखें: / से शुरू होने वाला हिस्सा अपने पहले का सब फेंक देता है।
"data/" + name 大多数时候能用 — Windows 在大多数地方也接受 / — 但拼接字符串会带来真实的 bug:斜杠重复或缺失、用 \ 拼出的 Windows 路径在 Linux 上失效、给用户看的路径风格不对。os.path.join()(或 pathlib 的 /)会使用正确的分隔符并处理边界情况。只要记住意外 #1:以 / 开头的部分会丢弃它前面的一切。
os.walk() — Visiting Every Folder in a Tree 🌳os.walk() — Tree के हर Folder तक जाना 🌳os.walk() — 访问树中的每个文件夹 🌳
os.walk(top) is a generator. Each time the loop asks for the next item, it visits one folder and hands back a 3-item tuple: (dirpath, dirnames, filenames). It keeps going until every folder below top has been visited.
os.walk(top) एक generator है। हर बार जब loop अगला item माँगता है, यह एक folder में जाता है और 3 items का tuple देता है: (dirpath, dirnames, filenames)। यह तब तक चलता है जब तक top के नीचे का हर folder देख न लिया जाए।
os.walk(top) 是一个 生成器。循环每要一次下一个元素,它就访问一个文件夹,并交回一个三元组:(dirpath, dirnames, filenames)。直到 top 下的每个文件夹都被访问过才停止。
dirnames and filenames hold names only — not full paths. Join them with dirpath to get a usable path.
dirnames और filenames में सिर्फ़ नाम होते हैं — पूरे paths नहीं। काम का path पाने के लिए इन्हें dirpath से जोड़ें।
dirnames 和 filenames 里 只有名字 — 不是完整路径。要和 dirpath 拼接才能得到可用的路径。
import os
for dirpath, dirnames, filenames in os.walk("project"):
print(f"Folder: {dirpath}")
print(f" Sub-folders: {dirnames}")
print(f" Files: {filenames}")
This is real output, and the order is not alphabetical: ['src', '.git', 'data', 'docs']. os.walk and os.listdir return names in whatever order the file system stores them. It can differ between computers, file systems and even runs. If your output must be stable (tests, reports, diffs), sort it.
यह असली output है, और क्रम वर्णानुसार नहीं है: ['src', '.git', 'data', 'docs']। os.walk और os.listdir नाम उसी क्रम में देते हैं जिसमें file system उन्हें रखता है। यह अलग कंप्यूटरों, file systems और यहाँ तक कि अलग runs में भी बदल सकता है। अगर output स्थिर चाहिए (tests, reports, diffs), तो sort करें।
这是真实输出,而且顺序 不是 字母序:['src', '.git', 'data', 'docs']。os.walk 和 os.listdir 按文件系统存储的顺序返回名字。不同电脑、不同文件系统、甚至不同次运行都可能不同。如果输出必须稳定(测试、报告、diff),请排序。
dirnames in place right now.
आपके loop का body चलता है। आप अभी dirnames को उसी जगह बदल सकते हैं।
你的循环体运行。此刻你可以 就地修改 dirnames。
dirnames, one by one, depth-first.
dirnames में बचे हर नाम में एक-एक करके, गहराई पहले, जाता है।
按深度优先,逐一进入 dirnames 中剩下的每个名字。
os.remove(f) inside a walk loop looks for f in the current working directory, not in dirpath. It fails with FileNotFoundError — or, worse, deletes a different file with the same name. Always write os.path.join(dirpath, f).
Walk loop के अंदर os.remove(f) f को dirpath में नहीं, current working directory में खोजता है। यह FileNotFoundError देता है — या उससे बुरा, उसी नाम की कोई दूसरी file delete कर देता है। हमेशा os.path.join(dirpath, f) लिखें।
在 walk 循环里写 os.remove(f),会在 当前工作目录 而不是 dirpath 中找 f。结果是 FileNotFoundError — 更糟的是,删掉另一个同名文件。请始终写 os.path.join(dirpath, f)。
Try It — The os.walk Explorer 🔭करके देखें — os.walk Explorer 🔭动手试试 — os.walk 探索器 🔭
This explorer replays real os.walk runs on the project/ tree from Section 07 — 12 combinations, all recorded from Python. Step through one yield at a time. The numbers on the folders show the visiting order. SKIP is {".git", "__pycache__"}.
यह explorer Section 07 के project/ tree पर असली os.walk runs दोहराता है — 12 combinations, सब Python से रिकॉर्ड किए गए। एक बार में एक yield आगे बढ़ें। Folders पर लिखे नंबर जाने का क्रम दिखाते हैं। SKIP है {".git", "__pycache__"}।
这个探索器重放在第 07 节 project/ 树上真实运行的 os.walk — 共 12 种组合,全部来自 Python 录制。一次前进一个 yield。文件夹上的数字表示访问顺序。SKIP 是 {".git", "__pycache__"}。
① Pick dirnames = … and play to the end — .git is still visited. ② Pick dirnames[:] = … — now it is skipped. ③ Keep the slice but switch to topdown=False — pruning stops working, because the children were already visited before their parent was yielded.
① dirnames = … चुनें और अंत तक चलाएँ — .git अब भी देखा जाता है। ② dirnames[:] = … चुनें — अब यह छूट जाता है। ③ Slice रखें पर topdown=False पर जाएँ — pruning काम करना बंद कर देती है, क्योंकि parent के yield होने से पहले ही children देखे जा चुके होते हैं।
① 选 dirnames = … 播放到底 — .git 依然被访问。② 选 dirnames[:] = … — 这次被跳过了。③ 保留切片但切换到 topdown=False — 剪枝失效,因为父目录被 yield 之前,子目录早已访问完。
Predictable Order with dirnames.sort()dirnames.sort() से तय क्रम用 dirnames.sort() 获得可预测顺序
import os
# Sort in place for a predictable order on every computer
for dirpath, dirnames, filenames in os.walk("project"):
dirnames.sort()
print(dirpath, sorted(filenames))
os.walk Patterns You Will Use Again and Again 🧰os.walk Patterns जो बार-बार काम आएँगे 🧰会反复用到的 os.walk 模式 🧰
Pattern 1 — Skip Folders (Pruning)Pattern 1 — Folders छोड़ना (Pruning)模式 1 — 跳过文件夹(剪枝)
os.walk decides where to go next by reading the same list object it gave you. Replace the contents of that list with dirnames[:] = … and the walk changes. Assign a brand-new list with dirnames = … and you only change your local variable — the walk never sees it.
os.walk आगे कहाँ जाना है, यह उसी list object को पढ़कर तय करता है जो उसने आपको दिया। dirnames[:] = … से उस list की सामग्री बदलें तो walk बदल जाता है। dirnames = … से नई list assign करें तो सिर्फ़ आपका local variable बदलता है — walk को कभी पता नहीं चलता।
os.walk 通过读取它交给你的 同一个列表对象 来决定下一步去哪里。用 dirnames[:] = … 替换列表内容,遍历就会改变。用 dirnames = … 赋一个新列表,只改变了你的局部变量 — 遍历根本看不到。
import os
skip = {".git", "__pycache__"}
print("--- WRONG: dirnames = [...] ---")
for dirpath, dirnames, filenames in os.walk("project"):
dirnames.sort()
dirnames = [d for d in dirnames if d not in skip] # a new local list
print(dirpath)
print("--- RIGHT: dirnames[:] = [...] ---")
for dirpath, dirnames, filenames in os.walk("project"):
dirnames[:] = sorted(d for d in dirnames if d not in skip) # same list, changed
print(dirpath)
Pattern 2 — Find Files by TypePattern 2 — Type से Files खोजना模式 2 — 按类型查找文件
import os
py_files = []
for dirpath, dirnames, filenames in os.walk("project"):
dirnames[:] = sorted(d for d in dirnames if d not in {".git", "__pycache__"})
for f in sorted(filenames):
if f.endswith(".py"):
py_files.append(os.path.join(dirpath, f)) # join name + folder!
print(f"Found {len(py_files)} Python files:")
for p in py_files:
print(" ", p)
Pattern 3 — Delete Bottom-Up with topdown=FalsePattern 3 — topdown=False से नीचे से ऊपर Delete模式 3 — 用 topdown=False 自底向上删除
import os
# topdown=False visits the DEEPEST folders first -
# you can only rmdir a folder after its children are gone
for dirpath, dirnames, filenames in os.walk("temp_data", topdown=False):
for f in filenames:
os.remove(os.path.join(dirpath, f))
print("removed file ", os.path.join(dirpath, f))
os.rmdir(dirpath)
print("removed folder", dirpath)
This loop shows why bottom-up order matters: a folder can only be removed after it is empty. For everyday work, shutil.rmtree(path) does the same thing in one line and handles more edge cases (links, read-only files on Windows).
यह loop दिखाता है कि नीचे-से-ऊपर का क्रम क्यों ज़रूरी है: folder तभी हटता है जब वह ख़ाली हो। रोज़ के काम के लिए shutil.rmtree(path) यही एक line में करता है और ज़्यादा किनारे के मामले संभालता है (links, Windows पर read-only files)।
这个循环展示了自底向上顺序 为什么 重要:文件夹只有清空后才能删除。日常工作中,shutil.rmtree(path) 一行就能完成,还处理更多边界情况(链接、Windows 上的只读文件)。
Pattern 4 — One Folder, Fast, with os.scandirPattern 4 — एक Folder, तेज़, os.scandir से模式 4 — 用 os.scandir 快速查看一个文件夹
os.scandir() returns DirEntry objects that already know their name, full path and type. Checking is_dir() usually costs no extra system call. os.walk itself is built on scandir.
os.scandir() DirEntry objects देता है जिन्हें अपना नाम, पूरा path और type पहले से पता होता है। is_dir() जाँचने में आमतौर पर कोई अतिरिक्त system call नहीं लगती। os.walk ख़ुद scandir पर बना है।
os.scandir() 返回 DirEntry 对象,它们已经知道自己的名字、完整路径和类型。检查 is_dir() 通常不需要额外的系统调用。os.walk 本身就构建在 scandir 之上。
import os
with os.scandir("project") as entries:
for entry in sorted(entries, key=lambda e: e.name):
kind = "folder" if entry.is_dir() else "file "
size = entry.stat().st_size if entry.is_file() else ""
print(kind, entry.name, size)
Environment Variables ⚙️Environment Variables ⚙️环境变量 ⚙️
Environment variables are named text values that a program receives from whatever started it — your terminal, an IDE, Docker, or a cloud server. They are the standard place for settings that change between machines: ports, database URLs, API keys.
Environment variables नाम वाली text values हैं जो program को उसे शुरू करने वाले से मिलती हैं — आपका terminal, IDE, Docker, या cloud server। मशीन-दर-मशीन बदलने वाली settings के लिए यही मानक जगह है: ports, database URLs, API keys।
环境变量是带名字的文本值,程序从启动它的东西那里接收 — 你的终端、IDE、Docker 或云服务器。它们是存放随机器变化的设置的标准位置:端口、数据库 URL、API 密钥。
import os
home = os.environ["HOME"] # KeyError if missing
db_url = os.getenv("DATABASE_URL", "sqlite:///dev.db") # safe, with a default
port = os.getenv("PORT", "8080")
print(home, db_url)
print(repr(port), type(port).__name__) # always a string!
print(int(port) + 1)
os.environ["APP_MODE"] = "production" # this process and its children only
os.environ["APP_REGION"] = "ap-south-1"
for key, value in sorted(os.environ.items()):
if key.startswith("APP_"):
print(f"{key}={value}")
try:
os.environ["NO_SUCH_VAR"]
except KeyError as e:
print("KeyError:", e)
| Way to readपढ़ने का तरीका读取方式 | If missingग़ायब होने पर不存在时 | Use whenकब इस्तेमाल करें适用场景 |
|---|---|---|
os.environ["KEY"] | KeyError | the program cannot run without itइसके बिना program चल ही नहीं सकता没有它程序无法运行 |
os.getenv("KEY") | None | it is optionalयह वैकल्पिक है它是可选的 |
os.getenv("KEY", "x") | "x" | there is a sensible defaultकोई समझदार default है有合理的默认值 |
os.environ["KEY"] = "v" | creates itबना देता है创建它 | this process and the child processes it starts — never the parent shellयह process और इसके शुरू किए child processes — parent shell कभी नहीं本进程及其启动的子进程 — 永远不影响父 shell |
Try It — Environment Labकरके देखें — Environment Lab动手试试 — 环境变量实验室
Set PORT and DEBUG the way a shell would, then see what config.py really prints. Every output here was recorded from Python with those exact variables set. Try DEBUG=0 and look at the last line.
PORT और DEBUG वैसे set करें जैसे shell करता है, फिर देखें config.py असल में क्या छापता है। यहाँ का हर output उन्हीं variables के साथ Python से रिकॉर्ड किया गया है। DEBUG=0 आज़माएँ और आख़िरी line देखें।
像 shell 那样设置 PORT 和 DEBUG,然后看 config.py 真正打印什么。这里每个输出都是在设置了这些变量后从 Python 录制的。试试 DEBUG=0,看最后一行。
Any non-empty string is True, so bool("0") and bool("false") are both True. Compare the text instead: os.getenv("DEBUG", "0").lower() in {"1", "true", "yes"}. And convert numbers with int() inside a try, so a bad value gives a clear message.
हर ख़ाली-नहीं string True है, इसलिए bool("0") और bool("false") दोनों True हैं। इसके बजाय text की तुलना करें: os.getenv("DEBUG", "0").lower() in {"1", "true", "yes"}। और numbers को try के अंदर int() से बदलें, ताकि ग़लत value पर साफ़ संदेश मिले।
任何非空字符串都是 True,所以 bool("0") 和 bool("false") 都是 True。应该比较文本:os.getenv("DEBUG", "0").lower() in {"1", "true", "yes"}。数字请在 try 中用 int() 转换,这样坏值能给出清楚的提示。
Windows uses USERPROFILE and USERNAME. For portable code, use os.path.expanduser("~") or pathlib.Path.home() for the home folder, and getpass.getuser() for the user name.
Windows USERPROFILE और USERNAME इस्तेमाल करता है। हर system पर चलने वाले code के लिए home folder को os.path.expanduser("~") या pathlib.Path.home() से, और user name को getpass.getuser() से लें।
Windows 使用 USERPROFILE 和 USERNAME。要写可移植代码,主目录请用 os.path.expanduser("~") 或 pathlib.Path.home(),用户名用 getpass.getuser()。
Process and System Information 🖥️Process और System की जानकारी 🖥️进程与系统信息 🖥️
import os
import subprocess
import sys
print(os.name) # 'posix' on Linux/macOS, 'nt' on Windows
print(sys.platform) # 'linux', 'darwin', 'win32'
print(os.getpid() > 0) # this process's ID (changes every run)
print(os.cpu_count()) # CPUs in the machine
print(os.process_cpu_count()) # CPUs THIS process may use (Python 3.13+)
# Run another program and capture its output
result = subprocess.run([sys.executable, "--version"], capture_output=True, text=True)
print(result.returncode, result.stdout.strip())
os.cpu_count() counts the CPUs in the machine. os.process_cpu_count() (new in Python 3.13) counts the CPUs this process is allowed to use — which can be fewer inside a container or with CPU limits. Use it to size a worker pool.
os.cpu_count() मशीन के CPUs गिनता है। os.process_cpu_count() (Python 3.13 में नया) वे CPUs गिनता है जिन्हें यह process इस्तेमाल कर सकता है — container में या CPU limits के साथ ये कम हो सकते हैं। Worker pool का आकार तय करने के लिए इसे इस्तेमाल करें।
os.cpu_count() 统计机器的 CPU 数。os.process_cpu_count()(Python 3.13 新增)统计 本进程被允许使用的 CPU 数 — 在容器中或有 CPU 限制时可能更少。用它来决定工作池大小。
os.system("ls -la") passes a string to the shell: it only returns an exit code, it breaks on Windows (no ls there), and building the string from user input invites shell injection. subprocess.run([...], capture_output=True, text=True) takes a list of arguments, captures the output, and never goes through a shell unless you ask.
os.system("ls -la") एक string shell को देता है: यह सिर्फ़ exit code लौटाता है, Windows पर टूटता है (वहाँ ls नहीं है), और user input से string बनाना shell injection को न्योता देता है। subprocess.run([...], capture_output=True, text=True) arguments की list लेता है, output पकड़ता है, और जब तक आप न कहें, shell से नहीं गुज़रता।
os.system("ls -la") 把字符串交给 shell:只返回退出码,在 Windows 上会失败(那里没有 ls),而用用户输入拼字符串会招来 shell 注入。subprocess.run([...], capture_output=True, text=True) 接收参数列表、捕获输出,除非你要求,否则从不经过 shell。
Real-World Scripts 🛠️असली काम की Scripts 🛠️实战脚本 🛠️
Five small scripts that solve problems people really have. Each one was run on the practice folder, and the output shown is the real output.
पाँच छोटी scripts जो लोगों की असली समस्याएँ हल करती हैं। हर एक practice folder पर चलाई गई, और दिखाया गया output असली है।
五个解决真实问题的小脚本。每个都在练习文件夹上运行过,显示的输出都是真实输出。
splitext()[1], count with Counter.splitext()[1] लें, Counter से गिनें।splitext()[1]、用 Counter 计数。getsize() of every file; skip files you cannot read.getsize() जोड़ें; जो file न पढ़ी जा सके उसे छोड़ें।getsize();跳过读不了的文件。getmtime() with a cutoff time.getmtime() की तुलना cutoff समय से करें।getmtime() 与截止时间比较。defaultdict(list).defaultdict(list) में समूह बनाएँ।defaultdict(list) 按文件名分组完整路径。1 · Count Files by Extension1 · Extension के हिसाब से Files गिनना1 · 按扩展名统计文件
import os
from collections import Counter
counts = Counter()
for dirpath, dirnames, filenames in os.walk("project"):
dirnames[:] = [d for d in dirnames if d not in {".git", "__pycache__"}]
for f in filenames:
ext = os.path.splitext(f)[1].lower() or "(no ext)"
counts[ext] += 1
for ext, n in counts.most_common():
print(f"{ext:10s} {n}")
2 · Total Size of a Folder2 · Folder का कुल आकार2 · 文件夹总大小
import os
def folder_size(root):
total = 0
for dirpath, _, filenames in os.walk(root):
for f in filenames:
try:
total += os.path.getsize(os.path.join(dirpath, f))
except OSError:
pass # broken link, no permission...
return total
size = folder_size("project")
print(f"{size:,} bytes ({size / 1024:.2f} KB)")
3 · Bulk Rename with a Dry Run3 · Dry Run के साथ थोक में नाम बदलना3 · 带演练的批量重命名
import os
DRY_RUN = True # look first, change later!
def rename_jpeg(root, dry_run):
for dirpath, dirnames, filenames in os.walk(root):
dirnames.sort()
for f in sorted(filenames):
if f.lower().endswith(".jpeg"):
old = os.path.join(dirpath, f)
new = os.path.join(dirpath, f[:-5] + ".jpg")
print(("would rename " if dry_run else "renamed ") + f"{old} -> {new}")
if not dry_run:
os.rename(old, new)
rename_jpeg("photos", DRY_RUN)
rename_jpeg("photos", dry_run=False)
print(sorted(os.listdir("photos/trip")))
On Linux and macOS, if the target name already exists, os.rename replaces it without asking (you saw this in the Operations Story, story 3). On Windows it raises FileExistsError instead. If you want overwriting on every system, use os.replace. If you want to protect existing files, check with os.path.exists(new) first.
Linux और macOS पर, अगर target नाम पहले से है, तो os.rename उसे बिना पूछे बदल देता है (Operations Story, कहानी 3 में आपने देखा)। Windows पर यह इसके बजाय FileExistsError देता है। हर system पर overwrite चाहिए तो os.replace इस्तेमाल करें। मौजूदा files बचानी हैं तो पहले os.path.exists(new) से जाँचें।
在 Linux 和 macOS 上,如果目标名已存在,os.rename 会 不加询问 地替换它(你在操作故事第 3 个故事中见过)。在 Windows 上则会抛出 FileExistsError。想在所有系统上都覆盖,请用 os.replace。想保护已有文件,请先用 os.path.exists(new) 检查。
4 · Files Changed in the Last 24 Hours4 · पिछले 24 घंटों में बदली Files4 · 过去 24 小时内修改的文件
import os
import time
cutoff = time.time() - 24 * 60 * 60 # 24 hours ago
recent = []
for dirpath, _, filenames in os.walk("logs"):
for f in filenames:
path = os.path.join(dirpath, f)
if os.path.getmtime(path) > cutoff:
recent.append(path)
print(f"{len(recent)} file(s) changed in the last 24 hours:", sorted(recent))
Note: this checks the last 24 hours, not "since midnight". For "today", compare against datetime.combine(date.today(), time.min).timestamp().
ध्यान दें: यह पिछले 24 घंटे जाँचता है, "आधी रात से" नहीं। "आज" के लिए datetime.combine(date.today(), time.min).timestamp() से तुलना करें।
注意:这里检查的是过去 24 小时,不是"从午夜起"。要表示"今天",请与 datetime.combine(date.today(), time.min).timestamp() 比较。
5 · Same File Name in Different Folders5 · अलग Folders में एक ही File नाम5 · 不同文件夹中的同名文件
import os
from collections import defaultdict
seen = defaultdict(list)
for dirpath, dirnames, filenames in os.walk("project"):
dirnames.sort()
for f in filenames:
seen[f].append(os.path.join(dirpath, f))
for name, paths in sorted(seen.items()):
if len(paths) > 1:
print(f"{name} appears in:")
for p in paths:
print(f" {p}")
The Modern Alternative — pathlib 🌟आधुनिक विकल्प — pathlib 🌟现代替代方案 — pathlib 🌟
pathlib (standard library since Python 3.4) wraps a path in an object. Instead of passing strings to many os.path functions, you ask the path itself. Most new code uses pathlib; os is still the tool for environment variables, processes and low-level work — and you will read os.path code for years.
pathlib (Python 3.4 से standard library में) path को एक object में लपेटता है। कई os.path functions को strings देने के बजाय, आप path से ही पूछते हैं। ज़्यादातर नया code pathlib इस्तेमाल करता है; environment variables, processes और low-level काम के लिए os अब भी औज़ार है — और os.path वाला code आप सालों तक पढ़ेंगे।
pathlib(自 Python 3.4 起属于标准库)把路径包装成对象。你不再把字符串传给一堆 os.path 函数,而是直接问路径本身。大多数新代码使用 pathlib;而环境变量、进程和底层操作仍要靠 os — 而且你还会读很多年的 os.path 代码。
| Taskकाम任务 | os / os.path |
|---|---|
| joinजोड़ना拼接 | os.path.join(a, "b") |
| file namefile नाम文件名 | os.path.basename(p) |
| extensionextension扩展名 | os.path.splitext(p)[1] |
| parentparent父目录 | os.path.dirname(p) |
| exists?मौजूद?存在? | os.path.exists(p) |
| read texttext पढ़ना读文本 | open(p).read() |
| all .py belowनीचे की सारी .py下面所有 .py | os.walk + endswithos.walk + endswithos.walk + endswith |
| Taskकाम任务 | pathlib |
|---|---|
| joinजोड़ना拼接 | a / "b" |
| file namefile नाम文件名 | p.name |
| extensionextension扩展名 | p.suffix |
| parentparent父目录 | p.parent |
| exists?मौजूद?存在? | p.exists() |
| read texttext पढ़ना读文本 | p.read_text() |
| all .py belowनीचे की सारी .py下面所有 .py | p.rglob("*.py") |
from pathlib import Path
p = Path("/home/aarav/data/report.csv")
print(p.name, p.stem, p.suffix)
print(p.parent)
new_p = Path("/home/aarav") / "reports" / "2026" / "jan.csv"
print(new_p)
# rglob: every .py file below a folder - often simpler than os.walk
for py_file in sorted(Path("project").rglob("*.py")):
print(py_file)
# Path.walk() (Python 3.12+) works like os.walk but gives Path objects
for dirpath, dirnames, filenames in Path("project/src").walk():
dirnames.sort()
print(dirpath, sorted(filenames))
Python 3.12 added Path.walk(), a pathlib version of os.walk. Python 3.14 added Path.copy(), Path.copy_into(), Path.move() and Path.move_into(), so copying and moving no longer need shutil. Check your Python version before using them.
Python 3.12 ने Path.walk() जोड़ा, जो os.walk का pathlib रूप है। Python 3.14 ने Path.copy(), Path.copy_into(), Path.move() और Path.move_into() जोड़े, ताकि copy और move के लिए shutil की ज़रूरत न रहे। इस्तेमाल से पहले अपना Python version जाँच लें।
Python 3.12 新增了 Path.walk(),即 pathlib 版的 os.walk。Python 3.14 新增了 Path.copy()、Path.copy_into()、Path.move() 和 Path.move_into(),复制和移动不再需要 shutil。使用前请确认你的 Python 版本。
Quick Reference 📋झटपट संदर्भ 📋速查表 📋
| CallCall调用 | What it doesक्या करता है作用 | Returnsलौटाता है返回 |
|---|---|---|
os.getcwd() | current folderमौजूदा folder当前文件夹 | str |
os.chdir(p) | change current folderमौजूदा folder बदलना切换当前文件夹 | None |
os.listdir(p) | names in a folder (unordered)folder के नाम (क्रम तय नहीं)文件夹中的名字(无序) | list[str] |
os.scandir(p) | entries with type infotype जानकारी वाली entries带类型信息的条目 | iterator |
os.mkdir(p) | one folderएक folder一个文件夹 | None |
os.makedirs(p, exist_ok=True) | folder + missing parentsfolder + ग़ायब parents文件夹 + 缺失的父目录 | None |
os.rmdir(p) | remove an empty folderख़ाली folder हटाना删除空文件夹 | None |
shutil.rmtree(p) | remove a folder and everything in itfolder और उसका सब कुछ हटाना删除文件夹及其全部内容 | None |
os.remove(p) | remove a filefile हटाना删除文件 | None |
os.rename(a, b) | rename / moveनाम बदलना / खिसकाना重命名 / 移动 | None |
os.replace(a, b) | rename, overwrite on every OSनाम बदलना, हर OS पर overwrite重命名,所有系统都覆盖 | None |
os.stat(p) | size, times, modeआकार, समय, mode大小、时间、模式 | stat_result |
os.path.join(*parts) | build a pathpath बनाना构建路径 | str |
os.path.splitext(p) | (root, ext)(root, ext)(root, ext) | tuple |
os.path.exists(p) | does it exist?क्या मौजूद है?是否存在? | bool |
os.walk(top) | every folder below toptop के नीचे हर foldertop 下的每个文件夹 | generator |
os.getenv(k, default) | read an env var safelyenv var सुरक्षित पढ़ना安全读取环境变量 | str | None |
os.process_cpu_count() | usable CPUs (3.13+)इस्तेमाल लायक CPUs (3.13+)可用 CPU 数(3.13+) | int | None |
Common Pitfalls 🕳️आम ग़लतियाँ 🕳️常见陷阱 🕳️
filenames holds names only. Always os.path.join(dirpath, f) before you open, stat or delete.filenames में सिर्फ़ नाम हैं। Open, stat या delete से पहले हमेशा os.path.join(dirpath, f) करें।filenames 只有名字。打开、stat 或删除之前,务必 os.path.join(dirpath, f)。dirnames = [...] changes nothing. Use dirnames[:] = [...], and only with topdown=True.dirnames = [...] कुछ नहीं बदलता। dirnames[:] = [...] इस्तेमाल करें, और सिर्फ़ topdown=True के साथ।dirnames = [...] 什么也不改变。请用 dirnames[:] = [...],并且只在 topdown=True 时有效。listdir, scandir and walk have no fixed order. Sort when order matters.listdir, scandir और walk का कोई तय क्रम नहीं। क्रम ज़रूरी हो तो sort करें।listdir、scandir、walk 都没有固定顺序。需要顺序时请排序。str. Convert with int(); compare booleans as text. bool("0") is True.str है। int() से बदलें; booleans की तुलना text के रूप में करें। bool("0") True है।str。用 int() 转换;布尔值按文本比较。bool("0") 是 True。os.remove on a folder raises IsADirectoryError on Linux but PermissionError on Windows and macOS. Catch OSError to cover both.os.remove Linux पर IsADirectoryError देता है पर Windows और macOS पर PermissionError। दोनों पकड़ने के लिए OSError पकड़ें।os.remove,在 Linux 上抛 IsADirectoryError,在 Windows 和 macOS 上抛 PermissionError。捕获 OSError 可同时覆盖两者。Golden Rules and Quiz 🏆सुनहरे नियम और Quiz 🏆黄金法则与小测验 🏆
os.path.join() or pathlib's /, never with +.os.path.join() या pathlib के / से बनाएँ, + से कभी नहीं।os.path.join() 或 pathlib 的 / 构建路径,绝不用 +。os.makedirs(p, exist_ok=True) is safe to run any number of times.os.makedirs(p, exist_ok=True) कितनी भी बार चलाना सुरक्षित है।os.makedirs(p, exist_ok=True) 运行多少次都安全。os.path.join(dirpath, f) for every file, dirnames[:] = … to skip folders.os.path.join(dirpath, f), folders छोड़ने के लिए dirnames[:] = …।os.path.join(dirpath, f),跳过文件夹用 dirnames[:] = …。getenv with a default, convert with care.getenv इस्तेमाल करें, ध्यान से convert करें।getenv,小心转换。os for environment, processes and low-level work.os रखें।os。Quick Quiz — 8 Questionsछोटा Quiz — 8 सवाल小测验 — 8 道题
The os module is your master key to the operating system: folders, files, paths, environment variables and processes. Its most powerful tool, os.walk, hands you one folder at a time as (dirpath, dirnames, filenames). Join names with dirpath, prune with dirnames[:], sort when order matters, dry-run before you change anything — and use pathlib for new path code.
os module operating system की आपकी master key है: folders, files, paths, environment variables और processes। इसका सबसे ताक़तवर औज़ार, os.walk, एक बार में एक folder (dirpath, dirnames, filenames) के रूप में देता है। नामों को dirpath से जोड़ें, dirnames[:] से prune करें, क्रम ज़रूरी हो तो sort करें, कुछ भी बदलने से पहले dry run करें — और नए path code के लिए pathlib इस्तेमाल करें।
os 模块是你通往操作系统的万能钥匙:文件夹、文件、路径、环境变量和进程。它最强大的工具 os.walk 每次以 (dirpath, dirnames, filenames) 交给你一个文件夹。用 dirpath 拼接名字,用 dirnames[:] 剪枝,需要顺序就排序,改动之前先演练 — 新的路径代码请用 pathlib。