উপরের ডিরেক্টরিতে থাকা পাইথন ক্লাসটি কীভাবে আমদানি করবেন?


210

আমি বর্তমানের উপরের একটি ডিরেক্টরিতে থাকা একটি ফাইলের একটি শ্রেণীর কাছ থেকে উত্তরাধিকারী হতে চাই।

অপেক্ষাকৃত ফাইলটি কি আমদানি করা সম্ভব?

উত্তর:


176

from ..subpkg2 import mod

পাইথন ডক্স অনুসারে: যখন প্যাকেজ শ্রেণিবিন্যাসের ভিতরে থাকে তখন দুটি বিন্দু ব্যবহার করুন, যেমন আমদানি বিবৃতি ডক বলে:

কোন মডিউলটি আমদানি করতে হবে তা নির্দিষ্ট করার সময় আপনাকে মডিউলটির পরম নাম উল্লেখ করতে হবে না। যখন কোনও মডিউল বা প্যাকেজ অন্য প্যাকেজের মধ্যে থাকে তখন প্যাকেজের নাম উল্লেখ না করে একই শীর্ষ প্যাকেজের মধ্যে একটি আপেক্ষিক আমদানি করা সম্ভব। নির্দিষ্ট মডিউল বা প্যাকেজটিতে শীর্ষস্থানীয় বিন্দু ব্যবহার করে fromআপনি নির্দিষ্ট নামগুলি উল্লেখ না করে বর্তমান প্যাকেজ শ্রেণিবিন্যাসকে কতটা উচ্চতর করতে হবে তা নির্দিষ্ট করতে পারেন। একটি শীর্ষস্থানীয় ডট মানে বর্তমান প্যাকেজ যেখানে আমদানি করা মডিউলটি বিদ্যমান। দুটি বিন্দু মানে একটি প্যাকেজ স্তর । তিনটি বিন্দু দুটি স্তরের উপরে থাকে ইত্যাদি So তাই আপনি যদি প্যাকেজের from . import modকোনও মডিউল থেকে চালনা করেন pkgতবে আপনার আমদানি শেষ হবে pkg.mod। আপনি যদি এর from ..subpkg2 import modমধ্যে থেকে নির্বাহ করেন pkg.subpkg1তবে আমদানি করবেনpkg.subpkg2.mod। আপেক্ষিক আমদানির জন্য স্পেসিফিকেশন পিইপি 328 এর মধ্যে রয়েছে ।

পিইপি 328 সম্পূর্ণ / আপেক্ষিক আমদানির বিষয়ে ডিল করে।


4
up1 = os.path.abspath ('..') sys.path.insert (0, up1)

পেপ 328 কেবল পাইথন-সংস্করণ দেখায়: 2.4, 2,5, 2.6। সংস্করণ 3 আরও জ্ঞানী আত্মার কাছে রেখে গেছে।
জিমেল

22
এটি ত্রুটিটি ভ্যালুএরার ট্রিগার করে: শীর্ষ স্তরের প্যাকেজ ছাড়িয়ে আপেক্ষিক আমদানির চেষ্টা করেছে
কার্লো

4
আমদানি-এর ফলাফলের ফলাফল: কোনও
অজানা

115
import sys
sys.path.append("..") # Adds higher directory to python modules path.

1
এটা আমার জন্য কাজ করে। এটি যুক্ত করার পরে, আমি সরাসরি প্যারেন্ট মডিউলগুলি আমদানি করতে পারি, ".." ব্যবহার করার দরকার নেই।
ইভান হু

8
এটি কেবল কাজ করে, মোটামুটিভাবে বলতে গেলে, যদি অ্যাপ্লিকেশনটির পিডাব্লুডি মান হয় - এটির বর্তমান ডাইরেক্টরয় পিতামাতার একটি সন্তান। সুতরাং, এটি যদি কাজ করেও, বহু ধরণের পদ্ধতিগত পরিবর্তনগুলি এটিকে অপসারণ করতে পারে।
ফিলিপ

এটি আমার পক্ষে পাশাপাশি উচ্চ স্তরের মডিউল আমদানি করার জন্য কাজ করেছে। আমি উচ্চ স্তরের অন্যান্য ফাইলগুলি লোড করতে এটি os.chdir ("..") দিয়ে ব্যবহার করি।
সুরেন্দ্র শ্রেষ্ঠ

এটি জিম থেকে উপরের উত্তর হিসাবে একই ত্রুটি ট্রিগার বলে মনে হচ্ছে।
কার্লো

81

@ জিমেলের উত্তরটি সঠিক যদি আপনি প্যাকেজ শ্রেণিবিন্যাসের উল্লেখ করেছেন তবে। যদি আপনি না করতে পারেন - যদি আপনার আসল প্রয়োজনটি যেমনটি আপনি প্রকাশ করেছেন তেমনই হয়, কেবল ডিরেক্টরিতে আবদ্ধ এবং প্যাকেজিংয়ের সাথে কোনও প্রয়োজনীয় সম্পর্ক ছাড়াই - তবে আপনাকে __file__প্যারেন্ট ডিরেক্টরিটি খুঁজে বের করার জন্য কাজ করতে হবে (কয়েকবার os.path.dirnameকল করবে; -), তারপর (যদি ডিরেক্টরিটি ইতিমধ্যেই নয় sys.path) শুরুতে যোগ অস্থায়ীভাবে সন্নিবেশ খুব শুরুতে Dir বলেন sys.path, __import__, অপসারণ আবার Dir বলেন - নোংরা কাজ প্রকৃতপক্ষে, কিন্তু, "আপনি যখন অবশ্যই, আপনাকে অবশ্যই" (এবং Pyhon কঠোর পরিশ্রম করে করতে প্রোগ্রামারকে যা করা উচিত তা করা থেকে কখনই থামান না - ঠিক যেমন আইএসও সি স্ট্যান্ডার্ড তার উপস্থায় "স্পিরিট অফ সি" বিভাগে বলেছে! -)।

এখানে একটি উদাহরণ যা আপনার জন্য কাজ করতে পারে:

import sys
import os.path
sys.path.append(
    os.path.abspath(os.path.join(os.path.dirname(__file__), os.path.pardir)))

import module_in_parent_dir

2
এটি পাইথন প্যাকেজের ভিতরে থাকা একটি ডিরেক্টরি যুক্ত করতে পারে যাতে sys.pathএকই নামটি বিভিন্ন নাম এবং সমস্ত সম্পর্কিত বাগের আওতায় পাওয়া যায়। পাইপিতে অটোপ্যাথ.পি বা প্যাঁচে _preamble.py ডিরেক্টরিগুলি উপরের দিকে ট্র্যাভার করার সময় শীর্ষ স্তরের প্যাকেজ সনাক্তকারী অনুসন্ধান মানদণ্ড ব্যবহার করে এটি সমাধান করুন।
jfs

4
আপনি হয়ত sys.path.remove(pathYouJustAdded)নতুন আমদানি করার পরে এমন কিছু করতে চাইবেন যাতে এই নতুন পথটি ধরে রাখা যায় না।
ম্যাথিয়াস

35

একটি ডিরেক্টরি থেকে আমদানি করুন মডিউল যা বর্তমান ডিরেক্টরি থেকে এক স্তর মাত্র:

from .. import module

38
আমি পেয়েছি: শীর্ষ স্তরের প্যাকেজ পেরিয়ে আপেক্ষিক আমদানির চেষ্টা করা হয়েছে :(
রিকার্ডো ই

25
from .. import module আমি ব্যবহার করে ত্রুটি পেয়েছি ভ্যালু এরির: প্রস্তাবনাটি অনুসরণ করে নন-প্যাকেজে আপেক্ষিক আমদানির চেষ্টা করা হয়েছে
ব্যবহারকারী 3428154

4

ডিরেক্টরিতে থাকা একটি মডিউলটি কীভাবে লোড করবেন

উপস্থাপনা: আমি পাইথনের ইকোসিস্টেমগুলিতে লোকেদের স্বাচ্ছন্দ্যে সাহায্য করার আশায় পূর্বের উত্তরের একটি উল্লেখযোগ্য পুনর্লিখন করেছি এবং আশা করি সবাইকে পাইথনের আমদানি ব্যবস্থায় সফলতার সেরা পরিবর্তন উপহার দিয়েছি।

এটি কোনও প্যাকেজের মধ্যে আপেক্ষিক আমদানি কভার করবে , যা আমি মনে করি ওপির প্রশ্নের সবচেয়ে সম্ভাব্য কেস।

পাইথন একটি মডুলার সিস্টেম

এই কারণেই আমরা লেখার import fooপরিবর্তে মূল নামের স্থান থেকে একটি মডিউল "foo" লোড করতে লিখি:

foo = dict();  # please avoid doing this
with open(os.path.join(os.path.dirname(__file__), '../foo.py') as foo_fh:  # please avoid doing this
    exec(compile(foo_fh.read(), 'foo.py', 'exec'), foo)  # please avoid doing this

পাইথন কোনও ফাইল-সিস্টেমে মিলিত হয় না

এই কারণেই আমরা পরিবেশে পাইথন এম্বেড করতে পারি যেখানে জাইথনের মতো ভার্চুয়াল সরবরাহ না করে কোনও ডিফাক্টো ফাইল সিস্টেম নেই।

একটি ফাইল সিস্টেম থেকে ডিউলড হওয়ার কারণে আমদানিগুলি নমনীয় হতে দেয়, এই নকশাটি সংরক্ষণাগার / জিপ ফাইলগুলি থেকে আমদানি, সিঙ্গেলনগুলি, বাইটকোড ক্যাচিং, সিএফআই এক্সটেনশানগুলি, এমনকি রিমোট কোড সংজ্ঞা লোডিংয়ের মতো জিনিসগুলির জন্য অনুমতি দেয়।

সুতরাং যদি আমদানিগুলি কোনও ফাইল সিস্টেমে সংযুক্ত না হয় তবে "একটি ডিরেক্টরি আপ" এর অর্থ কী? আমাদের কিছু হিউরিস্টিকস বাছাই করতে হবে তবে আমরা এটি করতে পারি, উদাহরণস্বরূপ প্যাকেজের মধ্যে কাজ করার সময় , কিছু হিউরিস্টিকস ইতিমধ্যে সংজ্ঞায়িত করা হয়েছে যা একই প্যাকেজের মধ্যে আপেক্ষিক আমদানিকে পছন্দ করে .fooএবং..foo কাজ করে। শান্ত!

যদি আপনি আন্তরিকভাবে কোনও ফাইল সিস্টেমে আপনার উত্স কোড লোডিং প্যাটার্নগুলি জোড়া দিতে চান তবে আপনি এটি করতে পারেন। আপনাকে নিজের হিউরিস্টিকস নির্বাচন করতে হবে এবং একধরণের আমদানি যন্ত্রপাতি ব্যবহার করতে হবে, আমি আমদানি সুপারিশ করব

পাইথনের ইম্পোর্টলিব উদাহরণটি এরকম কিছু দেখায়:

import importlib.util
import sys

# For illustrative purposes.
file_path = os.path.join(os.path.dirname(__file__), '../foo.py')
module_name = 'foo'

foo_spec = importlib.util.spec_from_file_location(module_name, file_path)
# foo_spec is a ModuleSpec specifying a SourceFileLoader
foo_module = importlib.util.module_from_spec(foo_spec)
sys.modules[module_name] = foo_module
foo_spec.loader.exec_module(foo_module)

foo = sys.modules[module_name]
# foo is the sys.modules['foo'] singleton

প্যাকেজিং

সরকারীভাবে এখানে একটি দুর্দান্ত উদাহরণ প্রকল্প পাওয়া যায়: https://github.com/pypa/sampleproject ject

পাইথন প্যাকেজটি হ'ল আপনার উত্স কোড সম্পর্কিত তথ্যের সংকলন, যা অন্য সরঞ্জামগুলিকে কীভাবে আপনার উত্স কোডটি অন্য কম্পিউটারে অনুলিপি করতে পারে এবং কীভাবে আপনার উত্স কোডটিকে সেই সিস্টেমের পথে সংহত করতে পারে যাতে import fooঅন্যান্য কম্পিউটারের জন্য কাজ করে (দোভাষী, নির্বিশেষে, হোস্ট অপারেটিং সিস্টেম, ইত্যাদি)

ডিরেক্টরি কাঠামো

fooকিছু ডিরেক্টরিতে (পছন্দমতো খালি ডিরেক্টরি) প্যাকেজের নাম দেওয়া যাক ।

some_directory/
    foo.py  # `if __name__ == "__main__":`  lives here

আমার পছন্দটি হ'ল setup.pyভাইবোন হিসাবে তৈরি করা foo.py, কারণ এটি সেটআপ.পি ফাইলটি সহজ করে লেখাকে সহজ করে তোলে, তবে আপনি যদি পছন্দ করেন তবে ডিফল্টরূপে সেটআপলগুলি যা কিছু করে সেটআপলুলগুলি পুনর্নির্দেশ করতে কনফিগারেশন লিখতে পারেন; উদাহরণস্বরূপ, foo.py"src /" ডিরেক্টরিতে অন্তর্ভুক্ত করা কিছুটা জনপ্রিয়, এখানে আচ্ছাদিত নয়।

some_directory/
    foo.py
    setup.py

#!/usr/bin/env python3
# setup.py

import setuptools

setuptools.setup(
    name="foo",
    ...
    py_modules=['foo'],
)

python3 -m pip install --editable ./  # or path/to/some_directory/

"সম্পাদনযোগ্য" ওরফে -eইনস্টল-পরিবেশের লাইব্রেরিতে বর্তমান সঠিক ফাইলগুলি অনুলিপি করার পরিবর্তে, এই ডিরেক্টরিতে উত্স ফাইলগুলি লোড করতে আমদানি করা যন্ত্রপাতিটিকে পুনর্নির্দেশ করবে। এটি কোনও বিকাশকারীর মেশিনে আচরণগত পার্থক্যের কারণও হতে পারে, আপনার কোডটি পরীক্ষা করে নিশ্চিত হন! পাইপ ব্যতীত অন্য সরঞ্জাম রয়েছে, তবে আমি পাইপটিকে পরিচয় করিয়ে দেওয়ার পরামর্শ দিই :)

আমি মডিউলের পরিবর্তে fooএকটি "প্যাকেজ" (একটি ডিরেক্টরি সম্বলিত ডিরেক্টরি __init__.py) তৈরি করতে চাই (একটি একক ".py" ফাইল), উভয় "প্যাকেজ" এবং "মডিউল" রুট নেমস্পেসে লোড করা যায়, মডিউলগুলি নেস্টেড নেমস্পেসের জন্য অনুমতি দেয়, আমরা যদি "আপেক্ষিক একটি ডিরেক্টরি আপ" আমদানি করতে চাই তবে এটি সহায়ক।

some_directory/
    foo/
        __init__.py
    setup.py

#!/usr/bin/env python3
# setup.py

import setuptools

setuptools.setup(
    name="foo",
    ...
    packages=['foo'],
)

আমি একটি করতে চান foo/__main__.py, এই একটি মডিউল রূপে প্যাকেজ চালানো পাইথন, যেমন পারবেন python3 -m fooচালানো হবে foo/__main__.pyযেমন __main__

some_directory/
    foo/
        __init__.py
        __main__.py  # `if __name__ == "__main__":`  lives here, `def main():` too!
    setup.py

#!/usr/bin/env python3
# setup.py

import setuptools

setuptools.setup(
    name="foo",
    ...
    packages=['foo'],
    ...
    entry_points={
        'console_scripts': [
            # "foo" will be added to the installing-environment's text mode shell, eg `bash -c foo`
            'foo=foo.__main__:main',
        ]
    },
)

এটিকে আরও কিছু মডিউল দিয়ে বেরিয়ে আসতে দেয়: মূলত, আপনার মতো ডিরেক্টরি কাঠামো থাকতে পারে:

some_directory/
    bar.py           # `import bar`
    foo/
        __init__.py  # `import foo`
        __main__.py
        baz.py       # `import foo.baz
        spam/           
            __init__.py  # `import foo.spam`
            eggs.py      # `import foo.spam.eggs`
    setup.py

setup.py প্রচলিতভাবে উত্স কোড সম্পর্কে মেটাডেটার তথ্য ধারণ করে যেমন:

  • "install_requires" নামক ইনস্টল করার জন্য কি নির্ভরতা প্রয়োজন
  • প্যাকেজ পরিচালনার জন্য কোন নামটি ব্যবহার করা উচিত ("নাম" ইনস্টল করুন / আনইনস্টল করুন), আমি আপনাকে এই ক্ষেত্রে আপনার প্রাথমিক পাইথন প্যাকেজটির নামটি মিলানোর পরামর্শ দিচ্ছি foo, যদিও হাইফেনগুলির জন্য আন্ডারস্কোর স্থাপন করা জনপ্রিয় though
  • লাইসেন্সিং তথ্য
  • পরিপক্কতা ট্যাগ (আলফা / বিটা / ইত্যাদি),
  • শ্রোতা ট্যাগ (বিকাশকারীদের জন্য, মেশিন লার্নিংয়ের জন্য),
  • একক পৃষ্ঠার ডকুমেন্টেশন সামগ্রী (একটি README এর মতো),
  • শেল নাম (আপনি ব্যাশের মতো ব্যবহারকারীর শেল এ টাইপ করা নামগুলি বা আপনি যে সূচনা মেনুর মতো গ্রাফিকাল ব্যবহারকারী শেলটিতে সন্ধান করেন),
  • পাইগন মডিউলগুলির একটি তালিকা এই প্যাকেজটি ইনস্টল করবে (এবং আনইনস্টল)
  • একটি ডিফাক্টো "রান পরীক্ষা" প্রবেশের পয়েন্ট python ./setup.py test

এটি খুব বিস্তৃত, এটি কোনও উত্সের মডিউল কোনও ডেভলপমেন্ট মেশিনে ইনস্টল করা থাকলে ফ্লাইতে সি এক্সটেনশানগুলি সংকলন করতে পারে। প্রতিদিনের উদাহরণের জন্য আমি পিওয়াইপিএ নমুনা সংগ্রহস্থলের সেটআপ.পিপি সুপারিশ করি

যদি আপনি একটি বিল্ড আর্টিক্ট প্রকাশ করে থাকেন, উদাহরণস্বরূপ কোডের একটি অনুলিপি যা প্রায় অভিন্ন কম্পিউটার চালানোর জন্য বোঝানো হয় তবে একটি প্রয়োজনীয়তা.txt ফাইল হুবহু নির্ভরতা সম্পর্কিত তথ্য স্ন্যাপশটের একটি জনপ্রিয় উপায়, যেখানে "ইনস্টল_রেইকায়ারস" ন্যূনতম এবং ক্যাপচার করার একটি ভাল উপায় where সর্বাধিক সামঞ্জস্যপূর্ণ সংস্করণ। যাইহোক, লক্ষ্য মেশিনগুলি যাইহোক যাইহোক প্রায় অভিন্ন, আমি অত্যন্ত অজগর উপসর্গের একটি টারবাল তৈরি করার পরামর্শ দিচ্ছি। এটি এখানে প্রবেশের জন্য খুব জটিল, খুব বিশদ হতে পারে। পরীক্ষা করে দেখুন pip installএর --targetবিশালাকার জন্য বিকল্প, অথবা virtualenv ওরফে venv।

উদাহরণ ফিরে

একটি ফাইল ওয়ান ডিরেক্টরি কীভাবে আমদানি করবেন:

Foo / স্প্যাম / ডিম.পি থেকে, যদি আমরা foo / baz এর কোড চাইতাম তবে আমরা এর নিখুঁত নেমস্পেসের মাধ্যমে এটি জানতে চাইতে পারি:

import foo.baz

আমরা যদি ভবিষ্যতে অন্য কিছু আপেক্ষিক bazবাস্তবায়নের মাধ্যমে ডিম.পি.কে অন্য কোনও ডিরেক্টরিতে স্থানান্তরিত করার ক্ষমতা সংরক্ষণ করতে চাই , আমরা আপেক্ষিক আমদানি যেমন ব্যবহার করতে পারি:

import ..baz

-5

পাইথন একটি মডুলার সিস্টেম

পাইথন কোনও ফাইল সিস্টেমে নির্ভর করে না

পাইথন কোডটি নির্ভরযোগ্যভাবে লোড করতে, সেই কোডটি একটি মডিউলে এবং সেই মডিউলটি পাইথনের লাইব্রেরিতে ইনস্টল করা থাকে।

ইনস্টল করা মডিউলগুলি সর্বদা শীর্ষ স্তরের নেমস্পেসের সাথে লোড করা যায় import <name>


সরকারীভাবে এখানে একটি দুর্দান্ত নমুনা প্রকল্প উপলব্ধ: https://github.com/pypa/sampleproject

মূলত, আপনার যেমন ডিরেক্টরি কাঠামো থাকতে পারে:

the_foo_project/
    setup.py  

    bar.py           # `import bar`
    foo/
      __init__.py    # `import foo`

      baz.py         # `import foo.baz`

      faz/           # `import foo.faz`
        __init__.py
        daz.py       # `import foo.faz.daz` ... etc.

আপনার setuptools.setup()মধ্যে ঘোষণা করতে ভুলবেন না setup.py,

সরকারী উদাহরণ: https://github.com/pypa/sampleproject/blob/master/setup.py

আমাদের ক্ষেত্রে আমরা সম্ভবত রফতানি করতে চাই bar.pyএবং foo/__init__.pyআমার সংক্ষিপ্ত উদাহরণ:

setup.py

#!/usr/bin/env python3

import setuptools

setuptools.setup(
    ...
    py_modules=['bar'],
    packages=['foo'],
    ...
    entry_points={}, 
        # Note, any changes to your setup.py, like adding to `packages`, or
        # changing `entry_points` will require the module to be reinstalled;
        # `python3 -m pip install --upgrade --editable ./the_foo_project
)

পাইথন লাইব্রেরিতে এখন আমরা আমাদের মডিউলটি ইনস্টল করতে পারি; পাইপের সাহায্যে the_foo_projectআপনি সম্পাদনা মোডে আপনার অজগর লাইব্রেরিতে ইনস্টল করতে পারেন , তাই আমরা এটি রিয়েল টাইমে কাজ করতে পারি

python3 -m pip install --editable=./the_foo_project

# if you get a permission error, you can always use 
# `pip ... --user` to install in your user python library

এখন যে কোনও অজগর প্রসঙ্গ থেকে আমরা আমাদের ভাগ করা পাইওয়াই মডেলগুলি এবং প্যাকেজগুলি লোড করতে পারি

foo_script.py

#!/usr/bin/env python3

import bar
import foo

print(dir(bar))
print(dir(foo))

2
আমার উল্লেখ করা উচিত আমি pip install --edit fooপ্রায়শই কোনও ভার্চুয়ালেনভের অভ্যন্তরে কাজ করার সময় আমার মডিউলটি ইনস্টল করি । আমি প্রায় কোনও মডিউল লিখি না যা ইনস্টল করার উদ্দেশ্যে নয়। আমি যদি কিছু ভুল বুঝি তবে আমি জানতে চাই।
থারস্মমনার

আমার এও উল্লেখ করা উচিত যে ভেনভ-অটো-ক্রিয়েশন টেস্ট স্যুট ব্যবহার করা যেমন টক্স যেমন editableডিমের লিঙ্ক এবং ইনস্টলড পাইথন মডিউলগুলি প্রতিটি উপায়ে একেবারে একরকম হয় না তেমন সহায়ক ; উদাহরণস্বরূপ, একটি সম্পাদনযোগ্য মডিউলে একটি নতুন নেমস্পেস যুক্ত করা আপনার পাথ লুকে দেখতে পাওয়া যাবে, তবে এটি যদি আপনার সেটআপ.পি ফাইলে রফতানি না হয় তবে এটি প্যাকেজ / ইনস্টল হবে না! আপনার ব্যবহারের
কেসটি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.