পাইথনে আমি কীভাবে একটি নেমস্পেস প্যাকেজ তৈরি করব?


141

পাইথনে, একটি নেমস্পেস প্যাকেজ আপনাকে বেশ কয়েকটি প্রকল্পের মধ্যে পাইথন কোড ছড়িয়ে দেওয়ার অনুমতি দেয়। আপনি যখন পৃথক ডাউনলোড হিসাবে সম্পর্কিত লাইব্রেরি প্রকাশ করতে চান এটি কার্যকর হয়। উদাহরণস্বরূপ, ডিরেক্টরি সহ Package-1এবং Package-2ইন PYTHONPATH,

Package-1/namespace/__init__.py
Package-1/namespace/module1/__init__.py
Package-2/namespace/__init__.py
Package-2/namespace/module2/__init__.py

শেষ ব্যবহারকারী import namespace.module1এবং করতে পারেন import namespace.module2

একটি নেমস্পেস প্যাকেজ সংজ্ঞায়নের সর্বোত্তম উপায় কী যাতে একাধিক পাইথন পণ্য সেই নামস্থানে মডিউলগুলি সংজ্ঞায়িত করতে পারে?


5
এটি দেখে মনে হচ্ছে মডিউল 1 এবং মডিউল 2 আসলে মডিউলগুলির চেয়ে সাবপ্যাকেজ। আমি যেমন এটি বুঝতে পারি, মডিউলটি মূলত একটি ফাইল। সম্ভবত subpkg1 এবং subpkg2 নাম হিসাবে আরও বোধ করতে পারে?
অ্যালান

উত্তর:


79

টি এল; ডিআর:

পাইথন ৩.৩-এ আপনাকে কিছু করতে হবে না, কেবল __init__.pyনিজের নাম স্থান প্যাকেজ ডিরেক্টরিতে কোনও রাখবেন না এবং এটি কেবল কাজ করবে। প্রাক -৩.৩-এ, pkgutil.extend_path()সমাধানটি সমাধান করুন pkg_resources.declare_namespace(), কারণ এটি ভবিষ্যত-প্রমাণ এবং ইতিমধ্যে অন্তর্ভুক্ত নেমস্পেস প্যাকেজগুলির সাথে সামঞ্জস্যপূর্ণ।


পাইথন ৩.৩ বিভক্ত নেমস্পেস প্যাকেজগুলি উপস্থাপন করে, পিইপি 420 দেখুন

এর অর্থ এখন তিন ধরণের অবজেক্ট রয়েছে যা একটি দ্বারা তৈরি করা যেতে পারে import foo:

  • একটি foo.pyফাইল দ্বারা প্রতিনিধিত্ব করা একটি মডিউল
  • একটি নিয়মিত প্যাকেজ, fooএকটি __init__.pyফাইল ধারণকারী ডিরেক্টরি দ্বারা প্রতিনিধিত্ব করা
  • fooকোনও __init__.pyফাইল ছাড়াই এক বা একাধিক ডিরেক্টরি দ্বারা প্রতিনিধিত্ব করা একটি নেমস্পেস প্যাকেজ

প্যাকেজগুলি মডিউলগুলিও, তবে এখানে আমি "মডিউল" বলার সময় "নন-প্যাকেজ মডিউল" বোঝায়।

প্রথমে এটি sys.pathএকটি মডিউল বা নিয়মিত প্যাকেজটির জন্য স্ক্যান করে । যদি এটি সফল হয়, এটি অনুসন্ধান বন্ধ করে মডিউল বা প্যাকেজটি তৈরি করে এবং ইনটাইটেলাইজ করে। যদি এটির কোনও মডিউল বা নিয়মিত প্যাকেজ না পাওয়া যায় তবে এটি কমপক্ষে একটি ডিরেক্টরি খুঁজে পাওয়া যায়, এটি একটি নেমস্পেস প্যাকেজ তৈরি করে এবং আরম্ভ করে।

মডিউল এবং নিয়মিত প্যাকেজগুলি সেগুলি থেকে তৈরি করা ফাইলে __file__সেট হয়ে .pyগেছে। নিয়মিত এবং নেমস্পেস প্যাকেজগুলি __path__সেগুলি তৈরি করা ডিরেক্টরি বা ডিরেক্টরিতে সেট করে।

আপনি যখন তা করবেন import foo.bar, উপরোক্ত অনুসন্ধানের জন্য প্রথম ঘটে foo, তারপর যদি একটি প্যাকেজ পাওয়া যায় নি, জন্য অনুসন্ধান barসঙ্গে সম্পন্ন করা হয় foo.__path__সার্চ পরিবর্তে পাথ হিসাবে sys.path। যদি foo.barপাওয়া যায়, fooএবং foo.barতৈরি করা হয় এবং আরম্ভ করা হয়।

তাহলে কীভাবে নিয়মিত প্যাকেজ এবং নেমস্পেস প্যাকেজগুলি মিশ্রিত হয়? সাধারণত এগুলি হয় না, তবে pkgutilঅন্তর্নিহিত নেমস্পেস প্যাকেজগুলি অন্তর্ভুক্ত করার জন্য পুরাতন স্পষ্টর নাম স্পেস প্যাকেজ পদ্ধতিটি বাড়ানো হয়েছে।

আপনার যদি কোনও বিদ্যমান নিয়মিত প্যাকেজ থাকে যা এর __init__.pyমতো থাকে:

from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)

... উত্তরাধিকার আচরণটি অনুসন্ধানের পথে অন্য কোনও নিয়মিত প্যাকেজ যুক্ত করা __path__। তবে পাইথন ৩.৩-তে এটি নামস্থান প্যাকেজ যুক্ত করে।

সুতরাং আপনার নিম্নলিখিত ডিরেক্টরি কাঠামো থাকতে পারে:

├── path1
   └── package
       ├── __init__.py
       └── foo.py
├── path2
   └── package
       └── bar.py
└── path3
    └── package
        ├── __init__.py
        └── baz.py

... আর যতদিন দুই __init__.pyআছে extend_pathলাইন (এবং path1, path2এবং path3আপনার মধ্যে আছে sys.path) import package.foo, import package.barএবং import package.bazসব কাজ করবে।

pkg_resources.declare_namespace(__name__) অন্তর্নিহিত নেমস্পেস প্যাকেজ অন্তর্ভুক্ত করার জন্য আপডেট করা হয়নি।


2
সেটআপলগুলি সম্পর্কে কী? আমার কি namespace_packagesবিকল্পটি ব্যবহার করতে হবে ? আর __import__('pkg_resources').declare_namespace(__name__)জিনিসটা?
কাওয়িং-চিউ

3
আমি কি যোগ namespace_packages=['package']করা উচিত setup.py?
লরেন্ট LAPORTE

1
@ ক্ল্যাক: এর সাথে namespace_packages=['package'], সেটআপ.পি ইজি-ইনফোতে একটি যোগ করবে namespace_packages.txt। এখনও প্রভাবগুলি জানেন না ...
লরেন্ট ল্যাপার্ট

1
@ কাভিং-চিউউ pkg_resources.declare_namespaceওভারের সুবিধা pkgutil.extend_pathহ'ল এটি নিরীক্ষণ চালিয়ে যাবে sys.path। এইভাবে, যদি sys.pathনেমস্পেসের প্যাকেজটি প্রথমে লোড হওয়ার পরে কোনও নতুন আইটেম যুক্ত করা হয় তবে নতুন পথের আইটেমের নেমস্পেসে থাকা প্যাকেজগুলি এখনও লোড হতে সক্ষম। ( __import__('pkg_resources')ওভার ব্যবহারের একটি সুবিধা import pkg_resourcesহ'ল আপনি যে pkg_resourcesহিসাবে প্রকাশিত হবেন না my_namespace_pkg.pkg_resources))
আর্থার ট্যাকা

1
@ ক্লােক এটি সেভাবে কাজ করে না (তবে এটির যেমন প্রভাব রয়েছে তেমন প্রভাব রয়েছে)। এটি সেই ফাংশন দিয়ে তৈরি সমস্ত প্যাকেজ নেমস্পেসের এবং বিশ্বস্ত তালিকাগুলির একটি বিশ্বব্যাপী তালিকা বজায় রাখে sys.pathsys.pathপরিবর্তনগুলি যখন এটি __path__কোনও নেমস্পেসের ক্ষেত্রে প্রভাব ফেলে কিনা তা পরীক্ষা করে এবং এটি যদি তা করে তবে এটি সেই __path__বৈশিষ্ট্যগুলিকে আপডেট করে ।
আর্থার টাক্কা

81

Pkgutil নামে একটি মানক মডিউল রয়েছে, যার সাহায্যে আপনি প্রদত্ত নেমস্পেসে মডিউলগুলি 'যুক্ত' করতে পারেন।

আপনার সরবরাহিত ডিরেক্টরি কাঠামোর সাথে:

Package-1/namespace/__init__.py
Package-1/namespace/module1/__init__.py
Package-2/namespace/__init__.py
Package-2/namespace/module2/__init__.py

আপনার উভয় Package-1/namespace/__init__.pyএবং Package-2/namespace/__init__.py(*) এই দুটি রেখা রাখা উচিত :

from pkgutil import extend_path
__path__ = extend_path(__path__, __name__)

(* যেহেতু আপনি তাদের মধ্যে একটি নির্ভরতা বর্ণনা করেছেন- আপনি জানেন না যে তাদের মধ্যে কোনটি প্রথমে স্বীকৃত হবে - আরও তথ্যের জন্য পিইপি 420 দেখুন)

ডকুমেন্টেশন যেমন বলে:

এটি প্যাকেজের নাম অনুসারে __path__ডিরেক্টরিগুলির প্যাকেজের সমস্ত উপ-ডিরেক্টরিকে যুক্ত sys.pathকরবে।

এখন থেকে আপনার এই দুটি প্যাকেজ স্বতন্ত্রভাবে বিতরণ করতে সক্ষম হওয়া উচিত।


17
বনাম আমদানি বনাম ('পিকেজি_সোর্সস') ব্যবহারের কী কী উপকারিতা রয়েছে? ডিক্লেয়ার_নামস্পেস (__ নাম )?
জোফোরকার

14
প্রথমত, __import__এই ক্ষেত্রে খারাপ শৈলী হিসাবে বিবেচিত হয় কারণ এটি সহজেই সরল আমদানির বিবৃতি দিয়ে প্রতিস্থাপন করা যেতে পারে। আরও উল্লেখযোগ্য বিষয় হল, pkg_res উত্স একটি মানহীন পাঠাগার। এটি সেটআপলগুলির সাথে আসে, সুতরাং এটি একটি অ ইস্যু, যদিও। দ্রুত গুগলিং প্রকাশ করে যে পেকগুইটেলটি 2.5 সালে প্রবর্তিত হয়েছিল এবং পিকেজি_সোর্সেস এটির পূর্বাভাস দেয়। তবুও, pkgutil একটি isicially- স্বীকৃত সমাধান। পি কেজি_সোর্স অন্তর্ভুক্তিটি পিইপি 365
মাইক হর্ডেক্কি

3
পিইপি 382 এর উদ্ধৃতি : বর্তমান স্থানের প্যাকেজগুলির জন্য প্রয়োজনীয় আবশ্যক পদ্ধতির ফলে নেমস্পেস প্যাকেজ সরবরাহের জন্য একাধিক সামান্য-অসম্পূর্ণ ব্যবস্থা রয়েছে। উদাহরণস্বরূপ, pkgutil * .pkg ফাইল সমর্থন করে; সেটআপললগুলি হয় না। একইভাবে, সেটআপলগুলি জিপ ফাইলগুলি পরিদর্শন করতে সমর্থন করে এবং এর _নামস্পেস_প্যাকেজ ভেরিয়েবলের অংশ যোগ করার পক্ষে সমর্থন করে, যেখানে পিকগুইটাল তা করে না।
ড্রাক গুয়ান

7
এই দুটি লাইন উভয় ফাইলের মধ্যে রাখা উচিত নয় : Package-1/namespace/__init__.py এবং Package-2/namespace/__init__.py প্রদান করে যে আমরা জানি না কোন প্যাকেজ দির প্রথমে তালিকাভুক্ত?
বুলা

3
@ ক্রিস্টোফার কার্লসন হ্যাঁ এটিই মূল বিষয়, আপনি যদি প্রথমে জানেন তবে এটি ঠিক আছে তবে আসল প্রশ্নটি আপনি কোনও গ্যারান্টি দিতে পারবেন যে কোনও পরিস্থিতিতে এটিই প্রথম হবে, অর্থাৎ অন্যান্য ব্যবহারকারীর জন্য?
বুলা

5

এই বিভাগটি বেশ স্ব-বর্ণনামূলক হওয়া উচিত।

সংক্ষেপে, নেমস্পেস কোডটি putুকিয়ে রাখুন, নাম স্থানটি ঘোষণার জন্য __init__.pyআপডেট করুন setup.pyএবং আপনি যেতে পারবেন।


9
প্রাসঙ্গিক লিঙ্কটি মারা যাওয়ার ক্ষেত্রে আপনার সর্বদা কোনও লিঙ্কের সম্পর্কিত অংশটি উদ্ধৃত করা উচিত।
টিনড_তুন

2

এটি একটি পুরানো প্রশ্ন, তবে কেউ সম্প্রতি আমার ব্লগে মন্তব্য করেছেন যে নেমস্পেস প্যাকেজগুলি সম্পর্কে আমার পোস্টিং এখনও প্রাসঙ্গিক, তাই আমি ভেবেছিলাম যে আমি এটি এখানে লিঙ্ক করব কারণ এটি কীভাবে এটি করা যায় তার একটি বাস্তব উদাহরণ প্রদান করে:

https://web.archive.org/web/20150425043954/http://cdent.tumblr.com/post/216241761/python-namespace-packages-for-tiddlyweb

যা চলছে তার মূল সাহসের জন্য এই নিবন্ধটিতে লিঙ্কগুলি:

http://www.siafoo.net/article/77#multiple-distributions-one-virtual-package

দ্য __import__("pkg_resources").declare_namespace(__name__)কৌতুক প্রায় কাছাকাছি ড্রাইভ মধ্যে প্লাগইনগুলির ব্যবস্থাপনা হয় TiddlyWeb এবং এ পর্যন্ত কাজ বলে মনে হয়।


-9

আপনার পাইথন নেমস্পেসের ধারণাগুলি সামনে পিছনে রয়েছে, পাইথনগুলিতে মডিউলগুলিতে প্যাকেজ স্থাপন করা সম্ভব নয়। প্যাকেজগুলিতে মডিউলগুলি অন্যভাবে নয়।

পাইথন প্যাকেজ হ'ল একটি ফাইলযুক্ত একটি ফোল্ডার __init__.py। মডিউল হ'ল একটি প্যাকেজের (বা সরাসরি PYTHONPATH) অন্য কোনও ফাইল যা ক.py এক্সটেনশন রয়েছে। সুতরাং আপনার উদাহরণে আপনার কাছে দুটি প্যাকেজ রয়েছে তবে কোনও মডিউল সংজ্ঞায়িত হয়নি। আপনি যদি প্যাকেজটি কোনও ফাইল সিস্টেম ফোল্ডার এবং মডিউল ফাইল বলে বিবেচনা করেন তবে আপনি দেখতে পাবেন কেন প্যাকেজগুলিতে মডিউল থাকে এবং অন্যভাবে নয়।

সুতরাং উদাহরণস্বরূপ প্যাকেজ -১ এবং প্যাকেজ -2 হ'ল পাইথন পথটি আপনি যে ফাইল সিস্টেমে রেখেছেন সেগুলি ফোল্ডারগুলি হ'ল নিম্নলিখিতগুলি থাকতে পারে:

Package-1/
  namespace/
  __init__.py
  module1.py
Package-2/
  namespace/
  __init__.py
  module2.py

আপনার কাছে এখন namespaceদুটি মডিউল module1এবং সহ একটি প্যাকেজ রয়েছে module2। এবং যদি আপনার কোনও যুক্তিসঙ্গত কারণ না থাকে তবে আপনার সম্ভবত মডিউলগুলি ফোল্ডারে রাখা উচিত এবং কেবলমাত্র নীচের মতো অজগর পথে:

Package-1/
  namespace/
  __init__.py
  module1.py
  module2.py

আমি এমন কিছু বিষয় নিয়ে কথা বলছি zope.xযেখানে একগুচ্ছ সম্পর্কিত প্যাকেজগুলি পৃথক ডাউনলোড হিসাবে প্রকাশিত হয়।
জোফোরকার

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

5
আপনি যদি পাইথনপথে প্যাকেজ -1 এবং প্যাকেজ 2-যোগ করেন তবে পাইথন দ্বারা কেবল প্যাকেজ -1 / নেমস্পেস / দেখা যাবে।
সেরেন লভবর্গ
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.