مقدمه
تقریباً هر برنامهای که با فایلها و پوشهها سروکار دارد، باید بتواند مسیر (Path) آنها را مدیریت کند. در گذشته، بیشتر برنامهنویسان پایتون برای این کار از ماژول os.path استفاده میکردند، اما از Python 3.4 به بعد ماژول قدرتمند pathlib به کتابخانه استاندارد پایتون اضافه شد و امروزه بهعنوان روش استاندارد و مدرن مدیریت مسیرها شناخته میشود.
ماژول pathlib رابطی شیءگرا (Object-Oriented) برای کار با مسیر فایلها ارائه میدهد و باعث میشود کدها خواناتر، کوتاهتر و مستقل از سیستمعامل باشند. به عبارت دیگر، بدون اینکه نگران تفاوت مسیرها در ویندوز، لینوکس یا macOS باشید، میتوانید تنها با استفاده از کلاسهای pathlib مسیرهای فایل را ایجاد، ویرایش و مدیریت کنید.
فرض کنید فایلی با نام wave.txt دارید. در سیستمعامل لینوکس ممکن است مسیر آن به شکل زیر باشد:
/Users/sammy/ocean/wave.txt
اما همین فایل در ویندوز معمولاً به این صورت نمایش داده میشود:
C:\Users\sammy\ocean\wave.txt
یکی از مهمترین مزیتهای pathlib این است که این تفاوتها را بهصورت خودکار مدیریت میکند و شما تنها روی منطق برنامه تمرکز خواهید کرد.
چرا از pathlib استفاده کنیم؟
استفاده از pathlib در پروژههای پایتون مزایای زیادی دارد، از جمله:
- خوانایی بسیار بیشتر نسبت به
os.path - مدیریت خودکار تفاوت مسیرها در سیستمعاملهای مختلف
- ایجاد مسیرهای فایل با حداقل کدنویسی
- جستجوی فایلها با الگوهای مختلف (Glob)
- دسترسی آسان به اطلاعات فایلها و پوشهها
- امکان پیمایش در ساختار دایرکتوریها
- رابط کاملاً شیءگرا و مدرن
به همین دلیل، در اکثر پروژههای جدید پایتون، استفاده از pathlib بهجای os.path توصیه میشود.
پیشنیازها
برای درک بهتر این آموزش بهتر است با مفاهیم زیر آشنا باشید:
- آشنایی مقدماتی با زبان Python 3
- مفاهیم فایل و پوشه در سیستمعامل
- کار با ترمینال یا Command Prompt
- آشنایی اولیه با ساختار مسیر فایلها (Path)
آشنایی با کلاس Path
مهمترین کلاس موجود در ماژول pathlib، کلاس Path است.
هر شیء (Object) از این کلاس نماینده یک مسیر روی سیستم فایل (Filesystem) خواهد بود؛ این مسیر میتواند مربوط به یک فایل یا یک پوشه باشد.
ابتدا کلاس Path را وارد برنامه میکنیم:
from pathlib import Path
سپس یک مسیر ایجاد میکنیم:
from pathlib import Path
wave = Path("ocean", "wave.txt")
print(wave)
خروجی در لینوکس یا macOS مشابه زیر خواهد بود:
ocean/wave.txt
در ویندوز نیز خروجی به شکل زیر نمایش داده میشود:
ocean\wave.txt
همانطور که مشاهده میکنید، نیازی نیست جداکننده مسیر (/ یا \) را خودتان مشخص کنید؛ pathlib با توجه به سیستمعامل، جداکننده مناسب را بهصورت خودکار انتخاب میکند.
مسیر نسبی (Relative Path)
در مثال قبلی، شیء wave یک مسیر نسبی (Relative Path) را نگهداری میکند.
wave = Path("ocean", "wave.txt")
این مسیر مشخص نمیکند فایل دقیقاً در کدام قسمت سیستم قرار دارد و تنها بیان میکند که فایل wave.txt داخل پوشه ocean قرار گرفته است.
برای مثال، ممکن است این فایل در هر یک از مسیرهای زیر وجود داشته باشد:
/home/user/ocean/wave.txt
یا
/home/research/ocean/wave.txt
بنابراین مسیر نسبی همیشه وابسته به محل اجرای برنامه است.
بخش دوم — ایجاد مسیرهای مطلق (Absolute Path) و ترکیب مسیرها
در بخش قبل با نحوه ساخت یک شیء از کلاس Path آشنا شدیم و دیدیم که مسیرهای نسبی چگونه ایجاد میشوند. اکنون یاد میگیریم چگونه مسیرهای مطلق (Absolute Path) را ایجاد کنیم.
مسیر مطلق چیست؟
برخلاف مسیر نسبی، مسیر مطلق محل دقیق فایل را روی سیستم مشخص میکند و هیچ ابهامی در آن وجود ندارد.
برای مثال:
/home/sammy/ocean/wave.txt
یا در ویندوز:
C:\Users\sammy\ocean\wave.txt
در هر دو مثال، محل دقیق فایل مشخص است.
دریافت پوشه Home کاربر
کلاس Path متدی به نام home() دارد که مسیر پوشه خانگی (Home Directory) کاربر فعلی را برمیگرداند.
from pathlib import Path
home = Path.home()
print(home)
خروجی در لینوکس ممکن است مشابه زیر باشد:
/home/sammy
در ویندوز نیز خروجی چیزی شبیه به این خواهد بود:
C:\Users\sammy
مزیت این روش این است که برنامه شما روی هر سیستمعاملی بدون تغییر کار خواهد کرد.
ساخت مسیر مطلق
اکنون میتوانیم مسیر فایل را بر اساس پوشه Home ایجاد کنیم.
from pathlib import Path
home = Path.home()
wave = Path(home, "ocean", "wave.txt")
print(wave)
خروجی:
/home/sammy/ocean/wave.txt
در این مثال:
Path.home()مسیر Home را برمیگرداند.- سپس با اضافه کردن پوشه
oceanو فایلwave.txt، مسیر کامل ساخته میشود.
ترکیب رشتهها و Path
یکی از قابلیتهای جذاب pathlib این است که سازنده کلاس Path فقط رشته (String) دریافت نمیکند؛ بلکه میتواند اشیای Path را نیز دریافت کند.
برای مثال:
from pathlib import Path
home = Path.home()
folder = Path("ocean")
file = Path("wave.txt")
path = Path(home, folder, file)
print(path)
خروجی:
/home/sammy/ocean/wave.txt
بدون نیاز به اتصال رشتهها یا استفاده از جداکننده مسیر، pathlib همه بخشها را بهدرستی کنار هم قرار میدهد.
ترکیب مسیرهای پیچیدهتر
حتی میتوانید چندین شیء Path را در کنار رشتههای معمولی ترکیب کنید.
from pathlib import Path
shark = Path(
Path.home(),
"ocean",
"animals",
Path("fish", "shark.txt")
)
print(shark)
خروجی:
/home/sammy/ocean/animals/fish/shark.txt
در این مثال مشاهده میکنید که:
Path.home()یک شیء Path است."ocean"و"animals"رشته هستند.Path("fish", "shark.txt")نیز یک شیء Path دیگر است.
کلاس Path تمام این موارد را بدون هیچ مشکلی با یکدیگر ترکیب کرده و مسیر نهایی را تولید میکند.
چرا این روش بهتر از os.path است؟
در گذشته معمولاً مسیرها به این شکل ساخته میشدند:
import os
path = os.path.join(
os.path.expanduser("~"),
"ocean",
"wave.txt"
)
اما با pathlib همان کد بسیار خواناتر خواهد بود:
from pathlib import Path
path = Path.home() / "ocean" / "wave.txt"
این شیوه علاوه بر کوتاهتر بودن، خوانایی بسیار بیشتری نیز دارد و امروزه در اکثر پروژههای جدید پایتون استفاده میشود.
بخش سوم — دسترسی به اطلاعات فایلها با pathlib
پس از ساخت یک شیء از کلاس Path، میتوانید به اطلاعات مختلف فایل یا پوشه نیز دسترسی داشته باشید. این قابلیت باعث میشود بدون نیاز به پردازش رشتهها، بتوانید نام فایل، پسوند آن و سایر ویژگیها را بهسادگی استخراج کنید.
دریافت نام فایل
ویژگی name نام فایل انتهایی مسیر را برمیگرداند.
from pathlib import Path
wave = Path("ocean", "wave.txt")
print(wave.name)
خروجی:
wave.txt
در این مثال، تنها نام فایل نمایش داده میشود و مسیر پوشهها حذف خواهد شد.
دریافت پسوند فایل
اگر بخواهید تنها پسوند فایل را به دست آورید، از ویژگی suffix استفاده کنید.
from pathlib import Path
wave = Path("ocean", "wave.txt")
print(wave.suffix)
خروجی:
.txt
این ویژگی هنگام بررسی نوع فایلها بسیار کاربردی است.
برای مثال میتوانید تشخیص دهید که آیا فایل یک تصویر است یا خیر:
if wave.suffix == ".jpg":
print("Image File")
یا:
if wave.suffix == ".pdf":
print("PDF File")
مشاهده مسیر کامل
اگر شیء Path را چاپ کنید، مسیر کامل نمایش داده میشود.
from pathlib import Path
wave = Path("ocean", "wave.txt")
print(wave)
خروجی:
ocean/wave.txt
بنابراین:
print(wave)
print(wave.name)
print(wave.suffix)
خروجی زیر را تولید میکند:
ocean/wave.txt
wave.txt
.txt
تغییر نام فایل با with_name()
یکی از متدهای کاربردی pathlib، متد with_name() است.
این متد بدون تغییر مسیر پوشهها، نام فایل را تغییر داده و یک شیء Path جدید ایجاد میکند.
from pathlib import Path
wave = Path("ocean", "wave.txt")
tides = wave.with_name("tides.txt")
print(wave)
print(tides)
خروجی:
ocean/wave.txt
ocean/tides.txt
همانطور که مشاهده میکنید:
- پوشه
oceanبدون تغییر باقی مانده است. - فقط نام فایل از
wave.txtبهtides.txtتغییر کرده است. - شیء اولیه (
wave) نیز تغییری نکرده و همچنان به فایل قبلی اشاره میکند.
چرا with_name() مفید است؟
فرض کنید میخواهید فایل خروجی را در همان پوشه ذخیره کنید اما با نام دیگری.
به جای ساخت دوباره کل مسیر:
output = Path("ocean", "result.txt")
میتوانید تنها نام فایل را تغییر دهید:
output = wave.with_name("result.txt")
این روش:
- خواناتر است.
- احتمال خطا را کاهش میدهد.
- در پروژههای بزرگ نگهداری کد را سادهتر میکند.
نمونه کاربردی
فرض کنید فایل زیر را پردازش کردهاید:
report.csv
و میخواهید خروجی را با نام دیگری ذخیره کنید.
from pathlib import Path
file = Path("reports", "report.csv")
new_file = file.with_name("report_backup.csv")
print(new_file)
خروجی:
reports/report_backup.csv
همان پوشه حفظ شده و فقط نام فایل تغییر کرده است.
بخش چهارم — پیمایش پوشهها با ویژگی parent
در بسیاری از پروژهها لازم است از مسیر یک فایل، به پوشهای که فایل در آن قرار دارد یا حتی پوشههای بالاتر دسترسی پیدا کنیم. ماژول pathlib این کار را با ویژگی parent بسیار ساده کرده است.
دسترسی به پوشه والد (Parent Directory)
فرض کنید مسیر زیر را داریم:
from pathlib import Path
shark = Path("ocean", "animals", "fish", "shark.txt")
print(shark)
print(shark.parent)
خروجی:
ocean/animals/fish/shark.txt
ocean/animals/fish
در این مثال، ویژگی parent پوشهای را برمیگرداند که فایل shark.txt داخل آن قرار دارد.
به بیان دیگر:
shark.txt
▲
│
ocean/animals/fish
دسترسی به چند سطح بالاتر
ویژگی parent خودش نیز یک شیء از نوع Path است. بنابراین میتوانید چندین بار پشت سر هم از آن استفاده کنید.
from pathlib import Path
shark = Path("ocean", "animals", "fish", "shark.txt")
print(shark.parent.parent)
خروجی:
ocean/animals
در این مثال:
- اولین
parentپوشهfishرا برمیگرداند. - دومین
parentپوشهanimalsرا برمیگرداند.
ساختار مسیر به شکل زیر است:
ocean
└── animals
└── fish
└── shark.txt
بنابراین:
shark.parent
برابر است با:
ocean/animals/fish
و:
shark.parent.parent
برابر است با:
ocean/animals
رفتن تا ریشه مسیر
میتوانید هر تعداد که لازم باشد از parent استفاده کنید.
from pathlib import Path
shark = Path("ocean", "animals", "fish", "shark.txt")
print(shark.parent.parent.parent)
خروجی:
ocean
و حتی:
print(shark.parent.parent.parent.parent)
خروجی:
.
در مسیرهای نسبی، نقطه (.) نشاندهنده دایرکتوری فعلی است.
اگر مسیر شما مطلق باشد، در نهایت به ریشه سیستم فایل خواهید رسید.
برای مثال:
path = Path("/home/sammy/ocean/animals/fish/shark.txt")
در این حالت:
print(path.parent)
خروجی:
/home/sammy/ocean/animals/fish
و:
print(path.parent.parent)
خروجی:
/home/sammy/ocean/animals
کاربردهای عملی parent
ویژگی parent در پروژههای واقعی بسیار کاربرد دارد. برای مثال:
- ذخیره فایل خروجی در همان پوشه فایل ورودی
- پیدا کردن پوشه پروژه
- ساخت مسیر فایلهای تنظیمات (Configuration)
- دسترسی به پوشههای بالاتر بدون استفاده از رشتهها
برای نمونه:
from pathlib import Path
config = Path("/project/config/settings.json")
logs = config.parent / "logs"
print(logs)
خروجی:
/project/config/logs
در این مثال، بدون نیاز به پردازش رشتهها، پوشه logs در کنار فایل تنظیمات ساخته شده است.
مزیت استفاده از parent
در گذشته برای بهدست آوردن پوشه والد معمولاً از توابعی مانند os.path.dirname() استفاده میشد که خوانایی کمتری داشتند.
در pathlib تنها با نوشتن:
path.parent
میتوانید به همان نتیجه برسید؛ این روش هم کوتاهتر است و هم درک آن برای سایر توسعهدهندگان سادهتر خواهد بود.
بخش پنجم — جستجوی فایلها با متد glob()
یکی از قدرتمندترین قابلیتهای ماژول pathlib، متد glob() است. این متد به شما اجازه میدهد فایلها و پوشهها را بر اساس یک الگوی مشخص (Pattern) جستجو کنید.
اگر قبلاً با Wildcardها در لینوکس یا ویندوز کار کرده باشید، استفاده از glob() برایتان کاملاً آشنا خواهد بود.
ساختار نمونه پروژه
فرض کنید ساختار پوشههای شما به شکل زیر است:
ocean
├── wave.txt
├── tides.txt
└── animals
└── fish
└── shark.txt
در این ساختار:
- دو فایل متنی داخل پوشه
oceanقرار دارند. - فایل
shark.txtداخل چند زیرپوشه قرار گرفته است.
پیدا کردن فایلهای یک پوشه
اگر بخواهید تمام فایلهای با پسوند .txt را فقط داخل پوشه ocean پیدا کنید، کافی است از glob() استفاده کنید.
from pathlib import Path
for txt_file in Path("ocean").glob("*.txt"):
print(txt_file)
خروجی:
ocean/wave.txt
ocean/tides.txt
الگوی *.txt
در این مثال:
"*.txt"
به این معناست:
*یعنی هر نامی.txtیعنی فقط فایلهایی که این پسوند را دارند.
بنابراین فایلهایی مانند موارد زیر پیدا خواهند شد:
wave.txt
tides.txt
notes.txt
report.txt
اما فایلهای زیر پیدا نمیشوند:
image.png
movie.mp4
document.pdf
جستجوی بازگشتی (Recursive)
گاهی فایلها داخل چندین پوشه قرار دارند و نمیخواهید تکتک پوشهها را بررسی کنید.
در این شرایط از الگوی زیر استفاده میشود:
from pathlib import Path
for txt_file in Path("ocean").glob("**/*.txt"):
print(txt_file)
خروجی:
ocean/wave.txt
ocean/tides.txt
ocean/animals/fish/shark.txt
** به چه معناست؟
در الگوی زیر:
**/*.txt
قسمت ** یعنی:
تمام پوشهها و زیرپوشهها را بهصورت بازگشتی (Recursive) جستجو کن.
به همین دلیل فایل shark.txt نیز پیدا میشود، در حالی که در مثال قبلی نمایش داده نمیشد.
جستجوی فایلهای Python
بهعنوان مثال، اگر بخواهید تمام فایلهای پایتون پروژه را پیدا کنید:
from pathlib import Path
for file in Path(".").glob("**/*.py"):
print(file)
این دستور تمام فایلهای .py را در پوشه فعلی و تمام زیرپوشهها نمایش میدهد.
جستجوی فایلهای تصویری
نمونه دیگر:
from pathlib import Path
for image in Path("images").glob("*.png"):
print(image)
خروجی:
images/logo.png
images/banner.png
images/avatar.png
جستجوی همه فایلها
اگر بخواهید تمام فایلها و پوشههای موجود در یک مسیر را مشاهده کنید:
from pathlib import Path
for item in Path("ocean").glob("*"):
print(item)
خروجی ممکن است مشابه زیر باشد:
ocean/wave.txt
ocean/tides.txt
ocean/animals
چه زمانی از glob استفاده کنیم؟
متد glob() در سناریوهای مختلف بسیار کاربردی است، از جمله:
- پیدا کردن تمام فایلهای یک نوع خاص (مانند
.txtیا.csv) - پردازش دستهای فایلها
- جستجوی فایلها در زیرپوشهها
- ساخت ابزارهای مدیریت فایل
- اسکن پروژههای نرمافزاری
- جمعآوری گزارشها یا لاگها
به دلیل سادگی و خوانایی بالا، glob() یکی از پرکاربردترین متدهای ماژول pathlib محسوب میشود.
بخش ششم — محاسبه مسیرهای نسبی با relative_to()
گاهی اوقات مسیر یک فایل بسیار طولانی است، اما شما فقط به بخشی از آن نیاز دارید. در چنین شرایطی، متد relative_to() یکی از کاربردیترین امکانات ماژول pathlib محسوب میشود.
این متد یک مسیر جدید ایجاد میکند که نسبت به یک مسیر دیگر محاسبه شده است.
مسیر نمونه
فرض کنید مسیر زیر را در اختیار دارید:
from pathlib import Path
shark = Path("ocean", "animals", "fish", "shark.txt")
مسیر کامل فایل برابر است با:
ocean/animals/fish/shark.txt
محاسبه مسیر نسبت به یک پوشه
اگر بخواهید مسیر فایل را نسبت به پوشه ocean به دست آورید:
from pathlib import Path
shark = Path("ocean", "animals", "fish", "shark.txt")
below_ocean = shark.relative_to(Path("ocean"))
print(below_ocean)
خروجی:
animals/fish/shark.txt
در این حالت، بخش ocean از ابتدای مسیر حذف شده است.
محاسبه نسبت به چند پوشه
همین کار را میتوان نسبت به مسیرهای عمیقتر نیز انجام داد.
from pathlib import Path
shark = Path("ocean", "animals", "fish", "shark.txt")
below_animals = shark.relative_to(
Path("ocean", "animals")
)
print(below_animals)
خروجی:
fish/shark.txt
همانطور که مشاهده میکنید، اکنون دو پوشه ابتدایی حذف شدهاند.
مشاهده همزمان نتایج
from pathlib import Path
shark = Path("ocean", "animals", "fish", "shark.txt")
print(shark)
print(shark.relative_to(Path("ocean")))
print(shark.relative_to(Path("ocean", "animals")))
خروجی:
ocean/animals/fish/shark.txt
animals/fish/shark.txt
fish/shark.txt
این مثال بهخوبی نشان میدهد که relative_to() مسیر را نسبت به نقطه شروع دلخواه شما محاسبه میکند.
اگر مسیر مرتبط نباشد چه میشود؟
متد relative_to() تنها زمانی کار میکند که مسیر دوم، بخشی از مسیر اول باشد.
برای مثال:
from pathlib import Path
shark = Path("ocean", "animals", "fish", "shark.txt")
shark.relative_to(Path("documents"))
در این حالت برنامه با خطا مواجه میشود.
خطای ValueError
خروجی مشابه زیر خواهد بود:
ValueError:
'ocean/animals/fish/shark.txt'
does not start with
'documents'
دلیل این خطا کاملاً مشخص است.
پوشه documents هیچ ارتباطی با مسیر فایل shark.txt ندارد؛ بنابراین پایتون نمیتواند مسیر نسبی معتبری ایجاد کند.
چه زمانی از relative_to استفاده کنیم؟
این متد در پروژههای واقعی کاربردهای فراوانی دارد، از جمله:
- حذف بخش مشترک مسیرها
- نمایش مسیرهای کوتاهتر به کاربران
- مدیریت ساختار پروژهها
- تولید مسیرهای خروجی
- ایجاد لینکهای نسبی بین فایلها
- ساخت ابزارهای مدیریت فایل و پوشه
برای مثال، اگر همه فایلهای پروژه داخل مسیر زیر قرار داشته باشند:
/project/src/modules/users/api.py
میتوانید فقط مسیر داخل پروژه را نمایش دهید:
from pathlib import Path
file = Path("/project/src/modules/users/api.py")
print(file.relative_to("/project"))
خروجی:
src/modules/users/api.py
این کار باعث میشود مسیرهای نمایشدادهشده کوتاهتر، خواناتر و مستقل از محل نصب پروژه باشند.
جمعبندی
ماژول pathlib یکی از بهترین امکانات استاندارد پایتون برای مدیریت مسیر فایلها و پوشهها است. این ماژول با ارائه یک رابط شیءگرا (Object-Oriented)، بسیاری از کارهایی را که قبلاً با os.path انجام میشد، سادهتر، خواناتر و قابل نگهداریتر کرده است.
در این مقاله با مهمترین قابلیتهای pathlib آشنا شدیم، از جمله:
- ساخت مسیرهای نسبی و مطلق
- استفاده از کلاس
Path - ترکیب مسیرها بدون نگرانی درباره تفاوت سیستمعاملها
- دریافت نام فایل و پسوند آن
- تغییر نام فایل با
with_name() - پیمایش پوشههای والد با
parent - جستجوی فایلها با استفاده از
glob() - محاسبه مسیرهای نسبی با
relative_to()
یکی از مهمترین مزیتهای pathlib این است که دیگر نیازی به اتصال رشتهها یا استفاده از جداکنندههای مختلف مسیر (/ یا \) ندارید. این ماژول تمام این تفاوتها را بهصورت خودکار مدیریت میکند و باعث میشود کد شما روی سیستمعاملهای مختلف بدون تغییر اجرا شود.
اگر قصد توسعه ابزارهای مدیریت فایل، اسکریپتهای خودکار، پروژههای دادهکاوی یا هر برنامهای که با فایلها و پوشهها سروکار دارد را دارید، یادگیری و استفاده از pathlib میتواند کیفیت و خوانایی کدهای شما را به شکل قابل توجهی افزایش دهد.
برای آشنایی با قابلیتهای بیشتر، میتوانید مستندات رسمی پایتون را نیز مطالعه کنید. امکاناتی مانند بررسی وجود فایل، ایجاد یا حذف پوشهها، تغییر نام فایلها، خواندن و نوشتن فایلها و بسیاری قابلیتهای دیگر نیز در این ماژول در دسترس هستند.
از همراهی شما با پارمین کلود سپاسگزاریم.
نظرات کاربران