Import به صورت Relative و Absolute در پایتون

ترجمه و تالیف : ارسطو عباسی
تاریخ انتشار : 13 خرداد 98
خواندن در 4 دقیقه
دسته بندی ها : پایتون

اگر قبلا روی یک پروژه پایتونی که شامل بیشتر از یک فایل می‌شود کار کرده باشید پس یقین دارم که از دستور import زیاد استفاده کرده‌اید و مجبور بوده‌اید که اسکریپت‌های نوشته شده دیگری را به پروژه خودتان اضافه کنید.

منظورمان در این مطلب import django و یا چیزهایی از این قبیل نیست. منظورمان import کردن فایل‌های مختلف داخل یک پروژه در فایل‌های دیگر است. برای همین ما در این مطلب قصد داریم شما را با درک درستی از شیوه‌های مختلف import یعنی حالت Relative و Absolute آشنا کنیم.

در این مطلب شما تفاوت این دو را مشاهده خواهید کرد و درک درستی از مزیت‌ها و عیب‌های هر کدام را دریافت می‌کنید. بیایید شروع کنیم!

یک نکته ابتدایی

قبل از اینکه سراغ حالت‌های مختلف import برویم بیایید خیلی سریع با دستور import آشنا شویم. پایتون یک زبان ماژولار است به همین دلیل شما می‌توانید ماژول‌های مختلفی را به یک فایل پایتونی اضافه کنید. حال ممکن است این ماژول‌ها را خودتان نوشته باشید و به صورت محلی در اختیار‌تان باشد و یا شاید هم یک ماژول استاندارد و یا آنلاین باشد که از آن استفاده می‌کنید.

منظور از ماژول یک فایل پایتونی با پسوند .py است. همچنین منظورمان از پکیج نیز به دایرکتوری گفته می‌شود که لیستی از ماژول‌ها در آن قرار دارد. 

وقتی که شما دو فایل .py داشته باشید و بخواهید از یکی از آن‌ها در فایل دیگری استفاده کنید، چه کاری انجام می‌دهید؟ آن را Import می‌کنیم.

  • Import چگونه کار می‌کند؟
  • اما شیوه کاری درست import به چه شکل است؟

بیایید تصور کنیم که ماژولی با نام abc را می‌خواهید import بکنید:

import abc

با اجرا کردن این دستور، اولین کاری که پایتون انجام می‌دهد این است که  به دنبال نام abc در sys.modules می‌گردد. این قسمت کش مربوط به تمام ماژول‌هایی است که قبلا آن‌‌ها را import کرده‌اید. 

اگر پایتون نتوانست نام ماژول را در این قسمت پیدا کند سری به ماژول‌های داخلی یا built-in می‌اندازد. این ماژول‌هایی است که در حین نصب پایتون توسط شما، به صورت خودکار نصب شده‌اند. می‌توان لیست کاملی از این ماژول‌ها را در صفحه Python Standard Library مشاهده کنید. 

اگر در این لیست نیز چیزی مشاهده نشد، پایتون به sys.path نگاه می‌کند که معمولا لیستی از فایل‌ها و دایرکتوری‌های مربوط به Current Directory فایل .py است. –یعنی همان فایلی که شما دستور import را اجرا کرده‌اید.–

وقتی که پایتون توانست ماژول را پیدا کند آن را در سراسر فایل در دسترس توسعه دهنده قرار می‌دهد. این بدان معناست که حال با قرار دادن abs در پروژه دیگر خطای NameError را دریافت نمی‌کنید.

اگر ماژول هیچ گاه پیدا نشود، پایتون به شما خطای ModuleNotFoundError را می‌دهد. برای پی بردن به اطلاعات بیشتر راجع به این موضوع می‌توانید مستندات مربوط به این لینک را مطالعه نمایید.

یک نکته امنیتی (مهم)

سیستم import در پایتون گاهی اوقات می‌تواند به عنوان یک خطر یا ریسک امنیتی برای پروژه‌تان به حساب بیاید. این به دلیل انعطاف پذیری بسیار زیاد سیستم ماژول‌های پایتون است. تصور کنید که شما یک کتابخانه غیر از موارد استاندارد یا محلی را وارد پروژه خودتان می‌کنید، اگر آن ماژول یک مشکل امنیتی داشته باشد، پروژه شما نیز با خطر مواجه خواهد شد. بنابراین بهتر است که import را به صورتی آگاهانه در چنین مواقعی استفاده کنید.

سینتکس import

حال که با شیوه کار کردن Import آشنایی پیدا کردیم نیاز است که سینتکس آن را نیز به خوبی یاد بگیریم. به صورت کلی دو حالت برای import‌ کردن وجود دارد. 

حالتی که شما منبع اصلی را به صوت کامل به پروژه‌تان اضافه می‌کنید. مانند:

import abc

و حالتی که شما در آن یک ماژول منحصر به فرد از یک پکیج را به پروژه می‌آورید. مانند:

from abc import xyz

خود xyz می‌تواند یک ماژول،‌ ساب پکیج، شئ، کلاس و یا یک تابع باشد. 

می‌توانید import را rename نیز بکنید. این کار باعث می‌شود که براساس نام تعیین شده شما پکیج فراخوانی شود:

import abc as hello

حال اگر دستور abc را در پروژه استفاده کنید، به شما خطا داده می‌شود اما اگر hello بنویسید این مشکل دیگر وجود ندارد.

دستور import را در دنیای برنامه‌نویسی پایتون به سه گروه تقسیم می‌کنند:

  • import مربوط به کتابخانه‌های استاندارد
  • import مربوط به کتابخانه‌های Third Party
  • import مربوط به پکیج‌های محلی

به مثال زیر توجه کنید:

# Standard library imports

import datetime

import os

# Third party imports

from flask import Flask

from flask_restful import Api

from flask_sqlalchemy import SQLAlchemy

# Local application imports

from local_module import local_class

from local_package import local_function

import به صورت Absolute

حال که به صورت مقدماتی با import آشنا شدید نیاز است که به صورت حرفه‌ای با آن کار بکنیم و ویژگی‌های بیشتری از آن را درک کنیم. ابتدای کار بیایید راجع به import به صورت Absolute یا مطلق صحبت کنیم. 

در حالت import مطلق ما وظیفه داریم که پکیج‌ها را به صورت Full path آدرس دهی کنیم. این آدرس‌دهی از جایی آغاز می‌شود که فایل مربوط به درخواست import حضور دارد. منظور دایرکتوری ریشه فایل .py است. 

یک مثال عملی

بیایید تصور کنیم که ما یک پروژه با ساختار زیر را در اختیار داریم:

└── project
    ├── package1
    │   ├── module1.py
    │   └── module2.py
    └── package2
        ├── __init__.py
        ├── module3.py
        ├── module4.py
        └── subpackage1
​​​​​​​            └── module5.py

ما در اینجا یک دایرکتوری اصلی با نام project داریم. این دایرکتوری دو ساب دایرکتوری با نام package1 و package2 را در اختیار دارد. همچنین در هر کدام از این دو دایرکتوری یکسری فایل .py مشاهده می‌شود و یک دایرکتوری دیگر نیز با نام subpackage1 وجود دارد که خود حاوی یک فایل .py است. 

بیایید تصور کنیم که:

  • package1/module2 شامل یک تابع به نام function1 است.
  • package2/__init__.py شامل یک کلاس به نام class1 است.
  • package2/subpackage1/module5.py نیز شامل یک تابع با نام function2 می‌شود.

در زیر می‌توانید شیوه درست import کردن به صورت مطلق یا Absolute را مشاهده بکنید:

from package1 import module1

from package1.module2 import function1

from package2 import class1

from package2.subpackage1.module5 import function2

اگر دقت کنید این کار درست شبیه به مسیردهی در یک محیط خط فرمانی است اما ما در اینجا بجای استفاده کردن از اسلش (/) از نقطه (.) استفاده می‌کنیم.

مزایا و معایب Absolute import

Absolute Import بیشتر از حالت دیگر ترجیح داده می‌شود به این دلیل که بسیار واضح و سر راست است. بیان‌مندی بسیار بالایی دارد و تنها با مشاهده کردن سینتکس می‌توان متوجه پکیج‌هایی شد که در پروژه import شده است. 

اما یک مشکلی که وجود دارد این است که import در حالت مطلق گاهی اوقات واقعا می‌تواند پیچیده و سردرگم کننده باشد:

from package1.subpackage2.subpackage3.subpackage4.module5 import function6

این واقعا عذاب آور است. بجای اینکار ما با یک جایگزین می‌توانیم کار بکنیم:

Import به صورت Relative

Import کردن در حالت نسبی یا Relative وابسته به محل کنونی مربوط به فایل .py است. با استفاده از این حالت ما می‌توانیم با بهره‌گیری از دستورات تغییر مسیر دایرکتوری، فرایند import را انجام دهیم.

سینتکس و یک مثال عملی

بیایید تصور کنیم که قصد داریم یک پکیج را از دایرکتوری کنونی و یا دایرکتوری قبلی به فایل .py ایمپورت کنیم. برای این کار می‌توانیم به صورت زیر عمل نماییم:

from .some_module import some_class

from ..some_package import some_function

from . import some_class

این دقیقا همان حالت آدرس دهی است که با استفاده کردن از دستور cd در محیط خط فرمان به آن دست پیدا می‌کنید. 

در خط ابتدایی مثال بالا می‌توان یک ماژول را مشاهده کرد که ما در اینجا قصد داریم یک کلاس منحصر به فرد از آن را import کنیم.

در خط دوم ما با یک پکیج روبرو هستیم که در دایرکتوری قبلی وجود دارد و ما قصد داریم یک تابع از آن را import کنیم.

در خط سوم نیز ما یک کلاس را از پکیج کنونی import می‌کنیم.

معایب و مزایای Relative Import

یک مزیت اصلی که برای Relative Import می‌توانیم در نظر بگیریم این است که بسیار مختصر و کوتاه نوشته می‌شود. براساس موقعیت کنونی‌تان آن‌ها می‌توانند دستورهای import مختصرتری را به شما بدهند.

اما مشکلی که Relative Import دارد این است که گاهی نمی‌تواند به خوبی استفاده شود و یا اینکه بسیار واضح نیست. به همین دلیل کمی تشخیص دادن منابع برای import شدن در این حالت سخت است.

در پایان

خب اگر این قسمت را می‌خوانید به این معناست که به خوبی مطالعه را به پایان رسانده‌اید و چیزهای زیادی را یاد گرفته‌اید. حال می‌توانید روی شیوه import کردن در پروژه‌های‌تان دقت بیشتری داشته باشید. 

همواره سعی کنید که از حالت Absolute برای پکیج‌های‌تان استفاده کنید اما زمانی که این حالت پیچیده شد به عنوان یک جایگزین سراغ Relative بروید.

گردآوری و تالیف ارسطو عباسی
آفلاین
user-avatar

من ارسطو‌ام :) کافی نیست؟! :)

دیدگاه‌ها و پرسش‌ها

برای ارسال نظر لازم است ابتدا وارد سایت شوید
در حال دریافت نظرات از سرور، لطفا منتظر بمانید