ভাইবোন প্যাকেজ আমদানি


199

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

নিম্নলিখিত কাঠামো সহ:

├── LICENSE.md
├── README.md
├── api
   ├── __init__.py
   ├── api.py
   └── api_key.py
├── examples
   ├── __init__.py
   ├── example_one.py
   └── example_two.py
└── tests
   ├── __init__.py
   └── test_one.py

ডিরেক্টরিগুলির স্ক্রিপ্টগুলি কীভাবে মডিউল থেকে আমদানি করে examplesএবং কমান্ডলাইন থেকে চালানো যায়?testsapi

এছাড়াও, আমি sys.path.insertপ্রতিটি ফাইলের জন্য কুৎসিত হ্যাক এড়াতে চাই । অবশ্যই এটি পাইথনে করা যায়, তাই না?


7
আমি সমস্ত sys.pathহ্যাকগুলি এড়িয়ে যাওয়া এবং একমাত্র প্রকৃত সমাধান যা এখনও পর্যন্ত পোস্ট করা হয়েছে তা পড়ার পরামর্শ দিচ্ছি (7 বছর পরে!)।
অরণ-ফে

1
যাইহোক, এখনও আরও একটি ভাল সমাধানের জন্য জায়গা আছে: লাইব্রেরি কোড থেকে এক্সিকিউটেবল কোড পৃথক করা; বেশিরভাগ সময় প্যাকেজের অভ্যন্তরে কোনও স্ক্রিপ্ট শুরু হওয়ার সাথে সাথে কার্যকর করা উচিত নয় ।
অরণ-ফে

এটি প্রশ্ন এবং উত্তর উভয়ই সহায়ক। আমি কেবল কৌতূহলী, কীভাবে "গ্রহণযোগ্য উত্তর" আসবে না যিনি এক্ষেত্রে এই অনুগ্রহপ্রাপ্ত ব্যক্তির মতো নয়?
ইন্ডমিনাস

@ আরান-ফে এগুলি সম্পর্কিত ও আমদানি ত্রুটির প্রশ্নোত্তর হিসাবে অন্তর্নিহিত অনুস্মারক। আমি এই পুরো সময়টি একটি হ্যাকের সন্ধান করছি, তবে গভীরভাবে আমি জানতাম সমস্যা থেকে বেরিয়ে আসার জন্য আমার উপায় ডিজাইনের সহজ উপায় ছিল। এটি যে এখানে পড়ার জন্য সবার জন্য সমাধান তা বলার অপেক্ষা রাখে না, তবে এটি একটি ভাল অনুস্মারক হিসাবে এটি অনেকের পক্ষে হতে পারে।
22

উত্তর:


69

সাত বছর পরে

যেহেতু আমি নীচের উত্তরটি লিখেছি, পরিবর্তিত sys.pathকরা এখনও একটি দ্রুত এবং নোংরা কৌশল যা ব্যক্তিগত স্ক্রিপ্টগুলির জন্য ভাল কাজ করে তবে বেশ কিছু উন্নতি হয়েছে

  • প্যাকেজটি ইনস্টল করা (একটি ভার্চুয়ালেনভে বা না) আপনি যা চান তা আপনাকে দেবে, যদিও আমি সেটআপটুলগুলি সরাসরি ব্যবহার করার চেয়ে পাইপ ব্যবহার করার পরামর্শ দিই (এবং setup.cfgমেটাডেটা সংরক্ষণ করার জন্য)
  • -mপতাকাটি ব্যবহার করা এবং প্যাকেজ হিসাবে চলমান কাজ করে (তবে আপনি যদি আপনার ওয়ার্কিং ডিরেক্টরিটি একটি ইনস্টলযোগ্য প্যাকেজে রূপান্তর করতে চান তবে কিছুটা বিশ্রী হয়ে উঠবে)।
  • পরীক্ষাগুলির জন্য, বিশেষত, পাইস্টেস্ট এ পরিস্থিতিতে এপিআই প্যাকেজটি সন্ধান করতে সক্ষম এবং sys.pathআপনার জন্য হ্যাকগুলির যত্ন করে

সুতরাং এটি সত্যিই নির্ভর করে আপনি কী করতে চান। আপনার ক্ষেত্রে, যদিও, যেহেতু মনে হয় যে আপনার লক্ষ্যটি কোনও পর্যায়ে একটি সঠিক প্যাকেজ তৈরি করা pip -e, তাই এটি এখনও নিখুঁত না হলেও, সম্ভবত এটি আপনার সেরা বেট।

পুরানো উত্তর

ইতিমধ্যে অন্য কোথাও বলা হয়েছে, ভয়াবহ সত্যটি হল যে আপনাকে কোনও __main__মডিউল থেকে ভাইবোনদের মডিউল বা পিতা-মাতা প্যাকেজ থেকে আমদানির অনুমতি দিতে কুৎসিত হ্যাকগুলি করতে হবে । ইস্যুটি পিইপি 366-তে বিস্তারিত রয়েছে । পিইপি 3122 আরও যুক্তিযুক্ত উপায়ে আমদানি পরিচালনা করার চেষ্টা করেছিল কিন্তু গাইডো এটিকে এক অ্যাকাউন্ট হিসাবে প্রত্যাখ্যান করেছে

একমাত্র ব্যবহারের ক্ষেত্রে স্ক্রিপ্টগুলি চলমান বলে মনে হচ্ছে যেগুলি মডিউলটির ডিরেক্টরিতে বাস করে যা আমি সবসময় একটি অ্যান্টিপ্যাটার্ন হিসাবে দেখেছি।

( এখানে )

যদিও, আমি নিয়মিতভাবে এই প্যাটার্নটি ব্যবহার করি

# Ugly hack to allow absolute import from the root folder
# whatever its name is. Please forgive the heresy.
if __name__ == "__main__" and __package__ is None:
    from sys import path
    from os.path import dirname as dir

    path.append(dir(path[0]))
    __package__ = "examples"

import api

এখানে path[0]আপনার চলমান স্ক্রিপ্টের উর্ধ্বস্থ ফোল্ডারে এবং dir(path[0])আপনার শীর্ষ স্তরের ফোল্ডার।

যদিও আমি এখনও এটির সাথে আপেক্ষিক আমদানি ব্যবহার করতে সক্ষম হয়েছি না তবে এটি শীর্ষ স্তর থেকে (আপনার উদাহরণের apiপ্যারেন্ট ফোল্ডারে) পরম আমদানির অনুমতি দেয় ।



2
পাইস্ট আপনার জন্য এপিআই প্যাকেজটি কীভাবে খুঁজে পাবে? মজাদারভাবে, আমি এই থ্রেডটি পেয়েছি কারণ আমি বিশেষত পাইস্ট এবং ভাইবোন প্যাকেজ আমদানি নিয়ে এই সমস্যাটিতে চলেছি।
জুনিয়রআইঙ্ক্যান্টার

1
আমার দুটি প্রশ্ন আছে, দয়া করে। 1. আপনার নিদর্শনটি __package__ = "examples"আমার জন্য ছাড়া কাজ করে বলে মনে হচ্ছে । আপনি কেন এটা ব্যবহার করুন? ২. কোন পরিস্থিতিতে __name__ == "__main__"তবে __package__তা নয় None?
আসল_পান্ডা

@ কৌতুক_পান্ডা সেটিং __packages__সাহায্য করে যদি আপনি নিখরচায় পথ যেমন আইরিক কাজ করতে চান examples.api(তবে এটি শেষ হয়ে গেছে যে আমি শেষ বার করেছি) এবং এই প্যাকেজটি চেক করা বেশিরভাগই অদ্ভুত পরিস্থিতি এবং ভবিষ্যতের প্রতিরোধের জন্য ব্যর্থতা ছিল না।
ইভপোক

165

Sys.path হ্যাক ক্লান্ত?

প্রচুর পরিমাণে sys.path.appendহ্যাক পাওয়া যায় তবে আমি সমস্যাটি সমাধানের একটি বিকল্প উপায় হাতে পেয়েছি।

সারসংক্ষেপ

  • কোডটিকে একটি ফোল্ডারে মুড়ে দিন (উদাঃ packaged_stuff)
  • ব্যবহারের তৈরি setup.pyস্ক্রিপ্ট যেখানে আপনি ব্যবহার setuptools.setup ()
  • পাইপ প্যাকেজটি সম্পাদনযোগ্য অবস্থায় ইনস্টল করুন pip install -e <myproject_folder>
  • ব্যবহার করে আমদানি করুন from packaged_stuff.modulename import function_name

সেটআপ

প্রারম্ভিক পয়েন্টটি আপনার সরবরাহ করা ফাইল কাঠামো, নামক ফোল্ডারে আবৃত myproject

.
└── myproject
    ├── api
       ├── api_key.py
       ├── api.py
       └── __init__.py
    ├── examples
       ├── example_one.py
       ├── example_two.py
       └── __init__.py
    ├── LICENCE.md
    ├── README.md
    └── tests
        ├── __init__.py
        └── test_one.py

আমি .রুট ফোল্ডারটি কল করব এবং আমার উদাহরণে এটি অবস্থিত C:\tmp\test_imports\

api.py

পরীক্ষার কেস হিসাবে, আসুন নিম্নলিখিতটি ব্যবহার করুন। /Api/api.py

def function_from_api():
    return 'I am the return value from api.api!'

test_one.py

from api.api import function_from_api

def test_function():
    print(function_from_api())

if __name__ == '__main__':
    test_function()

টেস্ট_এন চালানোর চেষ্টা করুন:

PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
  File ".\myproject\tests\test_one.py", line 1, in <module>
    from api.api import function_from_api
ModuleNotFoundError: No module named 'api'

আপেক্ষিক আমদানি অভ্যাস কাজ চেষ্টা করে:

ব্যবহারের from ..api.api import function_from_apiফলে ফলাফল হবে

PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
Traceback (most recent call last):
  File ".\tests\test_one.py", line 1, in <module>
    from ..api.api import function_from_api
ValueError: attempted relative import beyond top-level package

ধাপ

  1. রুট স্তর ডিরেক্টরিতে একটি সেটআপ.পি ফাইল তৈরি করুন

এর জন্য বিষয়বস্তু setup.pyহবে *

from setuptools import setup, find_packages

setup(name='myproject', version='1.0', packages=find_packages())
  1. ভার্চুয়াল পরিবেশ ব্যবহার করুন

আপনি যদি ভার্চুয়াল পরিবেশের সাথে পরিচিত হন, একটি সক্রিয় করুন এবং পরবর্তী পদক্ষেপে যান। ভার্চুয়াল পরিবেশের ব্যবহার করা হয় না একেবারে প্রয়োজনীয়, কিন্তু তারা হবে সত্যিই দীর্ঘ রান আপনাকে সাহায্য (আপনি চেয়ে বেশি 1 প্রকল্পের চলমান আছে ..)। সর্বাধিক প্রাথমিক পদক্ষেপগুলি (রুট ফোল্ডারে চালিত)

  • ভার্চুয়াল env তৈরি করুন
    • python -m venv venv
  • ভার্চুয়াল env সক্রিয় করুন
    • source ./venv/bin/activate(লিনাক্স, ম্যাকোস) বা ./venv/Scripts/activate(উইন)

এটি সম্পর্কে আরও জানতে, কেবলমাত্র গুগল "পাইথন ভার্চুয়াল এনভিউ টিউটোরিয়াল" বা এর অনুরূপ out আপনার সম্ভবত কখনও তৈরি করা, সক্রিয়করণ এবং নিষ্ক্রিয় করা ছাড়া অন্য কোনও আদেশের প্রয়োজন নেই।

একবার আপনি ভার্চুয়াল পরিবেশ তৈরি এবং সক্রিয় করার পরে, আপনার কনসোলটি বন্ধনীতে ভার্চুয়াল পরিবেশের নাম দেওয়া উচিত

PS C:\tmp\test_imports> python -m venv venv
PS C:\tmp\test_imports> .\venv\Scripts\activate
(venv) PS C:\tmp\test_imports>

এবং আপনার ফোল্ডার গাছটি দেখতে ** এর মতো হওয়া উচিত

.
├── myproject
   ├── api
      ├── api_key.py
      ├── api.py
      └── __init__.py
   ├── examples
      ├── example_one.py
      ├── example_two.py
      └── __init__.py
   ├── LICENCE.md
   ├── README.md
   └── tests
       ├── __init__.py
       └── test_one.py
├── setup.py
└── venv
    ├── Include
    ├── Lib
    ├── pyvenv.cfg
    └── Scripts [87 entries exceeds filelimit, not opening dir]
  1. পাইপ আপনার প্রকল্প সম্পাদনাযোগ্য স্থানে ইনস্টল করুন

আপনার শীর্ষ স্তরের প্যাকেজটি myprojectব্যবহার করে ইনস্টল করুন pip। কৌশলটি হ'ল ইনস্টলটি করার সময় -eপতাকাটি ব্যবহার করা । এইভাবে এটি সম্পাদনযোগ্য অবস্থায় ইনস্টল করা হবে এবং .py ফাইলগুলিতে করা সমস্ত সম্পাদনা স্বয়ংক্রিয়ভাবে ইনস্টল করা প্যাকেজটিতে অন্তর্ভুক্ত হবে।

রুট ডিরেক্টরিতে, চালান

pip install -e . (বিন্দুটি নোট করুন, এটি "বর্তমান ডিরেক্টরি" হিসাবে দাঁড়িয়েছে)

আপনি এটি ব্যবহার করে ইনস্টল করাও দেখতে পারেন pip freeze

(venv) PS C:\tmp\test_imports> pip install -e .
Obtaining file:///C:/tmp/test_imports
Installing collected packages: myproject
  Running setup.py develop for myproject
Successfully installed myproject
(venv) PS C:\tmp\test_imports> pip freeze
myproject==1.0
  1. যোগ myproject.আপনার আমদানির মধ্যে

মনে রাখবেন যে আপনাকে myproject.কেবলমাত্র আমদানিতে যুক্ত করতে হবে যা অন্যথায় কাজ করবে না। যে আমদানিগুলি setup.py& ছাড়া pip installকাজ করে তা এখনও কার্যকর থাকবে। নীচে একটি উদাহরণ দেখুন।


সমাধান পরীক্ষা করুন

এখন, api.pyউপরের test_one.pyসংজ্ঞায়িত এবং নীচে সংজ্ঞায়িত ব্যবহার করে সমাধানটি পরীক্ষা করা যাক ।

test_one.py

from myproject.api.api import function_from_api

def test_function():
    print(function_from_api())

if __name__ == '__main__':
    test_function()

পরীক্ষা চলছে

(venv) PS C:\tmp\test_imports> python .\myproject\tests\test_one.py
I am the return value from api.api!

* আরও ভার্বোস সেটআপ.পি উদাহরণের জন্য সেটআপলল ডক্স দেখুন ।

** বাস্তবে, আপনি আপনার ভার্চুয়াল পরিবেশটিকে আপনার হার্ড ডিস্কের যে কোনও জায়গায় রাখতে পারেন।


13
বিস্তারিত পোস্টের জন্য ধন্যবাদ। এখানে আমার সমস্যা। আপনি যা বলেছিলেন তা আমি যদি করি এবং আমি একটি পাইপ ফ্রিজ করি -e git+https://username@bitbucket.org/folder/myproject.git@f65466656XXXXX#egg=myproject, কীভাবে সমাধান করবেন আমি তার একটি আইডিয়া পেয়েছি ?
সি সোমবার

2
আপেক্ষিক আমদানি সমাধান কাজ করে না কেন? আমি আপনাকে বিশ্বাস করি, তবে আমি পাইথনের সংশ্লেষিত সিস্টেমটি বোঝার চেষ্টা করছি।
জারেড

8
কারও সাথে একটি সমস্যা আছে ModuleNotFoundError? আমি এই পদক্ষেপগুলি অনুসরণ করে একটি ভার্চুয়ালেনভের মধ্যে 'মাইপ্রজেক্ট' ইনস্টল করেছি এবং যখন আমি কোনও ব্যাখ্যামূলক অধিবেশন প্রবেশ করি এবং রান import myprojectকরি তখন ModuleNotFoundError: No module named 'myproject'? pip list installed | grep myprojectদেখায় যে এটি সেখানে আছে, ডিরেক্টরিটি সঠিক ছিল এবং উভয়ের ভেরিওন pipএবং pythonসঠিক হওয়া যাচাই করা আছে।
ThatKind

2
আরে @ np8, এটি কাজ করে আমি ঘটনাক্রমে venv এবং অপারেটিং সিস্টেম :) এটা ইনস্টল pip list, শো প্যাকেজ যখন pip freezeশো অদ্ভুত নাম যদি পতাকা দিয়ে ইনস্টল -e
Grzegorz Krug

3
কীভাবে আপেক্ষিক আমদানিগুলি কীভাবে কাজ করা যায় তা নির্ধারণের চেষ্টা করার জন্য প্রায় 2 ঘন্টা ব্যয় করেছেন এবং এই উত্তরটি হ'ল অবশেষে বুদ্ধিমান কিছু করেছিল। 👍👍
গ্রাহাম লী

43

testsফোল্ডারে পাইথন ফাইলগুলির শীর্ষে আমি সন্নিবেশ করানো অন্য বিকল্পটি এখানে রয়েছে :

# Path hack.
import sys, os
sys.path.insert(0, os.path.abspath('..'))

1
+1 সত্যিই সহজ এবং এটি পুরোপুরি কার্যকর হয়েছিল। আপনার আমদানিতে অভিভাবক শ্রেণি যুক্ত করতে হবে (উদাহরণস্বরূপ, api.api, উদাহরণ.example_two) তবে আমি সেভাবে পছন্দ করি।
ইভান প্লেস

10
আমি মনে করি এটি newbies (আমার মতো) এর কাছে উল্লেখ করার মতো যে ..এখানে আপনি যে ডিরেক্টরিটি চালাচ্ছেন --- সেই পরীক্ষার / উদাহরণ ফাইলটি অন্তর্ভুক্ত ডিরেক্টরি নয় not আমি প্রকল্প ডিরেক্টরি থেকে সম্পাদন করছি, এবং এর ./পরিবর্তে আমার প্রয়োজন । আশাকরি এটি কাউকে সাহায্য করবে।
জোশুয়া ডিটওয়েলার

@ জোশডেটওয়েলার, হ্যাঁ নিখুঁতভাবে। আমি সেটা সম্পর্কে সচেতন ছিলাম না। ধন্যবাদ।
ডক

1
এটি একটি খারাপ উত্তর। পথ হ্যাক করা ভাল অনুশীলন নয়; অজগর বিশ্বে এটি কতটা ব্যাঘাতজনক। এই প্রশ্নের একটি প্রধান বিষয় ছিল হ্যাক এই ধরণের এড়াতে গিয়ে কীভাবে আমদানি করা যায় তা দেখা।
jtcotton63

sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))@ জোশুয়াডেটওয়েলার
vldbnc

31

আপনার প্রয়োজন নেই এবং হ্যাক করা উচিত নয় sys.pathযতক্ষণ না এটি প্রয়োজন হয় এবং এই ক্ষেত্রে এটি না হয়। ব্যবহার করুন:

import api.api_key # in tests, examples

প্রকল্পের ডিরেক্টরি থেকে চালান: python -m tests.test_one

আপনার সম্ভবত ভিতরে চলে যেতে হবে tests(যদি তারা এপিআই এর ইউনিটসেট থাকে) apiএবং python -m api.testসমস্ত পরীক্ষা চালানোর জন্য দৌড়াতে হবে (অনুমান করে আছে __main__.py) বা পরিবর্তে python -m api.test.test_oneচালানো উচিত test_one

এছাড়াও আপনি এটি (পাইথন প্যাকেজ নয়) __init__.pyথেকে সরিয়ে ফেলতে পারেন examplesএবং ভার্চুয়ালেনভের উদাহরণগুলি apiইনস্টল করতে পারেন যেখানে উদাহরণস্বরূপ, pip install -e .ভার্চুয়ালেনভের apiসঠিক ব্যবস্থা থাকলে ইনপ্লেস প্যাকেজ ইনস্টল করতে পারেন setup.py


@ অ্যালেক্স উত্তরটি ধরে নিবে না যে পরীক্ষাগুলি এপিআই পরীক্ষাগুলি ব্যতীত যেখানে অনুচ্ছেদে ব্যতীত যেখানে এটি স্পষ্টভাবে "যদি তারা এপিআইয়ের ইউনিটসেট হয়" বলে থাকে
jfs

দুর্ভাগ্যক্রমে তখন আপনি রুট দির থেকে দৌড়তে আটকে গেছেন এবং পাইচার্ম এখনও তার সুন্দর ফাংশনগুলির জন্য ফাইলটি খুঁজে পান না
mhstnsc

@ এমএইচএসটিএনএসসি: এটি সঠিক নয়। python -m api.test.test_oneযখন ভার্চুয়ালেনভ সক্রিয় হবে তখন আপনার যে কোনও জায়গা থেকে দৌড়াতে সক্ষম হওয়া উচিত । আপনি যদি পরীক্ষাগুলি চালানোর জন্য পাইচার্ম কনফিগার করতে না পারেন তবে একটি নতুন স্ট্যাক ওভারফ্লো প্রশ্ন জিজ্ঞাসা করার চেষ্টা করুন (যদি আপনি এই বিষয়টিতে কোনও বিদ্যমান প্রশ্নটি খুঁজে না পান)।
jfs

@jfs আমি ভার্চুয়াল এনভিও পথটি মিস করেছি তবে আমি কোনও ডিরেক্টরি থেকে এই স্টাফটি চালানোর জন্য শেবাং লাইনের চেয়ে বেশি কিছু ব্যবহার করতে চাই না। এটি পাইচার্মের সাথে চলার বিষয়ে নয়। পাইচার্মের সাথে ডেভসরাও জানত যে তাদের সমাপ্তি রয়েছে এবং এমন ফাংশনগুলির মধ্য দিয়ে ঝাঁপ দাও যা আমি কোনও সমাধান দিয়ে কাজ করতে পারি না।
mhstnsc

। @mhstnsc একটি যথাযথ কুঁড়েঘর যথেষ্ট অনেক ক্ষেত্রে করতে virtualenv পাইথন বাইনারি কোন শালীন পাইথন আইডিই একটি virtualenv সমর্থন করা উচিত এটা বিন্দু (।
JFS

9

ভাইবোন / আপেক্ষিক আমদানি হ্যাক ছাড়াই অপ্রাসঙ্গিক প্রকল্পগুলির মধ্যে কোড ভাগ করে নেওয়ার উদ্দেশ্যে দেখতে পাইথোনোলজির এখনও উপলব্ধি আমার কাছে নেই। সেদিন অবধি এটি আমার সমাধান is এর থেকে স্টাফ আমদানি করার জন্য examplesবা testsদেখতে ..\apiএটি দেখতে এমন হবে:

import sys.path
import os.path
# Import from sibling directory ..\api
sys.path.append(os.path.dirname(os.path.abspath(__file__)) + "/..")
import api.api
import api.api_key

এটি আপনাকে এপিআই প্যারেন্ট ডিরেক্টরিটি দেবে এবং আপনার "/ .." কনট্যাক্টেশন sys.path.append (os.path.dirname (os.path.dirname (os.path.abspath ( ফাইল ))) প্রয়োজন হবে না )
কামিলো সানচেজ

4

ভাইবোন প্যাকেজ আমদানির জন্য, আপনি [sys.path] [2] মডিউলটির সন্নিবেশ বা সংযোজন পদ্ধতি ব্যবহার করতে পারেন :

if __name__ == '__main__' and if __package__ is None:
    import sys
    from os import path
    sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
    import api

আপনি যদি আপনার স্ক্রিপ্টগুলি নীচে চালু করে থাকেন তবে এটি কাজ করবে:

python examples/example_one.py
python tests/test_one.py

অন্যদিকে, আপনি আপেক্ষিক আমদানিও ব্যবহার করতে পারেন:

if __name__ == '__main__' and if __package__ is not None:
    import ..api.api

এক্ষেত্রে আপনাকে আপনার স্ক্রিপ্টটি '-m' যুক্তি দিয়ে চালু করতে হবে (দ্রষ্টব্য, এই ক্ষেত্রে আপনাকে অবশ্যই '.py' এক্সটেনশনটি দিতে হবে না ):

python -m packageName.examples.example_one
python -m packageName.tests.test_one

অবশ্যই, আপনি দুটি পদ্ধতির মিশ্রন করতে পারেন, যাতে আপনার স্ক্রিপ্টটি যেভাবেই বলা হোক না কেন এটি কাজ করবে:

if __name__ == '__main__':
    if __package__ is None:
        import sys
        from os import path
        sys.path.append( path.dirname( path.dirname( path.abspath(__file__) ) ) )
        import api
    else:
        import ..api.api

আমি ক্লিক ফ্রেমওয়ার্কটি ব্যবহার করছিলাম যার __file__গ্লোবাল নেই তাই আমাকে নিম্নলিখিতটি ব্যবহার করতে হয়েছিল: sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(sys.argv[0]))))তবে এটি এখন কোনও ডিরেক্টরিতে কাজ করে
গ্যামা গেমস

3

TLDR

এই পদ্ধতির জন্য সেটআপলগুলি, পাথ হ্যাকগুলি, অতিরিক্ত কমান্ড লাইন আর্গুমেন্টগুলির প্রয়োজন হয় না বা আপনার প্রকল্পের প্রতিটি ফাইলের মধ্যে প্যাকেজের শীর্ষ স্তর নির্দিষ্ট করে।

আপনি যেটিকে আপনার হতে ডেকেছেন সেটির মূল ডিরেক্টরিতে একটি স্ক্রিপ্ট তৈরি করুন __main__এবং সেখান থেকে সমস্ত কিছু চালান। আরও ব্যাখ্যা জন্য পড়া চালিয়ে যান।

ব্যাখ্যা

একসাথে নতুন পাথ হ্যাক করা, অতিরিক্ত কমান্ড লাইন আরগস বা আপনার প্রতিটি প্রোগ্রামের কোড সহ ভাইবোনদের সনাক্ত করতে কোড যুক্ত না করে এটি সম্পন্ন করা যেতে পারে।

এই ব্যর্থতার কারণ হিসাবে আমি বিশ্বাস করি যে আগে উল্লেখ করা হয়েছিল প্রোগ্রামগুলি তাদের __name__সেট হিসাবে রয়েছে set__main__ । যখন এটি ঘটে তখন স্ক্রিপ্টটি প্যাকেজের শীর্ষ স্তরে থাকা হিসাবে নিজেকে স্বীকার করে এবং ভাইবাল ডিরেক্টরিতে স্ক্রিপ্টগুলি স্বীকৃতি দিতে অস্বীকার করে।

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

ধারণার প্রমাণ নিম্নলিখিত কাঠামোর সাথে একটি dir মধ্যে:

.
|__Main.py
|
|__Siblings
   |
   |___sib1
   |   |
   |   |__call.py
   |
   |___sib2
       |
       |__callsib.py

Main.py নিম্নলিখিত কোড রয়েছে:

import sib1.call as call


def main():
    call.Call()


if __name__ == '__main__':
    main()

sib1 / call.py এ রয়েছে:

import sib2.callsib as callsib


def Call():
    callsib.CallSib()


if __name__ == '__main__':
    Call()

এবং sib2 / কলস.বি.পিতে রয়েছে:

def CallSib():
    print("Got Called")

if __name__ == '__main__':
    CallSib()

আপনি যদি এই উদাহরণ পুনরুত্পাদন করেন আপনি লক্ষ্য করবেন যে কল করার Main.pyফলে "কল পেয়েছেন" মুদ্রিত হওয়ার পরে ফলাফলটি কল করা sib2/callsib.py সত্ত্বেও সংজ্ঞায়িত হিসাবে sib2/callsib.pyতৈরি হবে sib1/call.py। তবে যদি সরাসরি কল করা হয় sib1/call.py(আমদানিতে উপযুক্ত পরিবর্তন করার পরে) এটি ব্যতিক্রম ছুঁড়ে দেয়। যদিও এটি স্ক্রিপ্ট দ্বারা তার মূল ডিরেক্টরিতে কল করার সময় এটি কাজ করেছিল, এটি যদি প্যাকেজের শীর্ষ স্তরে থাকে বলে নিজেকে বিশ্বাস করে তবে এটি কাজ করবে না।


2

আমি কীভাবে এটি পরিচালনা করেছি তা প্রদর্শনের জন্য আমি একটি নমুনা প্রকল্প তৈরি করেছি, যা উপরে উল্লিখিত হিসাবে সত্যই অন্য একটি সিএস.পথ হ্যাক। পাইথন ভাইবোন আমদানির উদাহরণ , যা এর উপর নির্ভর করে:

if __name__ == '__main__': import os import sys sys.path.append(os.getcwd())

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


এটি কেবল তখনই কাজ করে যদি আপনি স্ক্রিপ্টের মূল ডিরেক্টরি থেকে চালিত হন
ইভপোক

1

সম্পর্কিত কোডটিতে কীভাবে আমদানি বিবৃতি লেখা আছে তা আপনাকে দেখতে হবে। যদি examples/example_one.pyনিম্নলিখিত আমদানি বিবৃতি ব্যবহার করে:

import api.api

... তারপরে এটি প্রত্যাশা করে যে প্রকল্পের মূল ডিরেক্টরিটি সিস্টেমের পথে হবে।

কোনও হ্যাক ছাড়াই এটি সমর্থন করার সবচেয়ে সহজ উপায় (যেমন আপনি এটি রেখেছেন) এটি হবে শীর্ষ স্তরের ডিরেক্টরি থেকে উদাহরণগুলি চালানো, এটি:

PYTHONPATH=$PYTHONPATH:. python examples/example_one.py 

পাইথন 2.7.1 আমি নিম্নলিখিত পাবেন: $ python examples/example.py Traceback (most recent call last): File "examples/example.py", line 3, in <module> from api.api import API ImportError: No module named api.api। আমিও সঙ্গে একই পেতে import api.api
জাচউইল

আমার উত্তর Updated ... আপনি কি ইম্পোর্ট পাথ, প্রায় কোন উপায় বর্তমান ডিরেক্টরির যোগ আছে।
এজে।

1

কেবলমাত্র কেউ যদি অ্যালাইপসে পাইদেব ব্যবহার করে এখানেই শেষ হয়: আপনি প্রজেক্ট-> প্রোপার্টি ব্যবহার করে এবং বাম মেনুতে পাইদেব-পাইথনপ্যাথের অধীনে বাহ্যিক গ্রন্থাগার স্থাপন করে বাইরের লাইব্রেরি ফোল্ডার হিসাবে ভাইবোনটির পিতামাতার পথটি (এবং এইভাবে কলিং মডিউলটির পিতামাতাকে) যুক্ত করতে পারেন । তারপরে আপনি আপনার ভাইবোন থেকে আমদানি করতে পারেন, যেমন ।from sibling import some_class


-3

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

আপনি যখন কোনও ফাইল আমদানি করেন, প্রথমে দোভাষা বর্তমান ডিরেক্টরিটি পরীক্ষা করে তারপরে গ্লোবাল ডিরেক্টরিগুলি অনুসন্ধান করে।

ভিতরে examplesবা testsআপনি কল করতে পারেন:

from ..api import api

পাইথন Traceback (most recent call last): File "example_one.py", line 3, in <module> from ..api import api ValueError: Attempted relative import in non-package
২.7.১ এর

2
ওহ, তারপরে আপনার __init__.pyশীর্ষ স্তরের ডিরেক্টরিতে একটি ফাইল যুক্ত করা উচিত । অন্যথায় পাইথন এটিকে মডিউল হিসাবে ব্যবহার করতে পারে না

8
এটি কাজ করবে না। সমস্যাটি হল এই যে উর্ধ্বস্থ ফোল্ডারে একটি প্যাকেজ নয় এটা যে যেহেতু মডিউল এর নয়, __name__হয় __main__পরিবর্তে package.module, পাইথন না তার পিতা বা মাতা প্যাকেজ তাই দেখতে পারেন, .কিছুই পয়েন্ট।
ইভপোক
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.