পাইথন: একটি উপ-প্যাকেজ বা উপ-মডিউল আমদানি করা হচ্ছে


90

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

ডিরেক্টরি বিন্যাস

dir
 |
 +-- test.py
 |
 +-- package
      |
      +-- __init__.py
      |
      +-- subpackage
           |
           +-- __init__.py
           |
           +-- module.py

Init .py এর সামগ্রী

উভয় package/__init__.pyএবং package/subpackage/__init__.pyখালি।

কন্টেন্ট module.py

# file `package/subpackage/module.py`
attribute1 = "value 1"
attribute2 = "value 2"
attribute3 = "value 3"
# and as many more as you want...

test.py(3 সংস্করণ) এর সামগ্রী

সংস্করণ 1

# file test.py
from package.subpackage.module import *
print attribute1 # OK

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

সংস্করণ 2

# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
from module import attribute1

আইটেম অনুসারে আইটেমটি আমদানির একটি নিরাপদ উপায়, তবে এটি ব্যর্থ হয়, পাইথন এটি চায় না: বার্তাটি দিয়ে ব্যর্থ হয়: "মডিউল নামে কোনও মডিউল নেই"। যাহোক …

# file test.py
import package.subpackage.module
from package.subpackage import module # Alternative
print module # Surprise here

… বলে <module 'package.subpackage.module' from '...'>। সুতরাং এটি একটি মডিউল, তবে এটি কোনও মডিউল / -P 8-O নয় u

সংস্করণ 3

# file test.py v3
from package.subpackage.module import attribute1
print attribute1 # OK

এই এক কাজ করে। সুতরাং আপনি হয় পুরোপুরি ওভারকিল উপসর্গটি ব্যবহার করতে বাধ্য হন বা # 1 সংস্করণ হিসাবে অনিরাপদ উপায়টি ব্যবহার করতে এবং পাইথন দ্বারা নিরাপদ উপায়ে ব্যবহার করতে নিষেধ করেছেন? সবচেয়ে ভাল উপায়, যা নিরাপদ এবং আনুষঙ্গিক দীর্ঘ উপসর্গ এড়ানোর একমাত্র পাইথন প্রত্যাখ্যান করে? এটি কি কারণ এটি ভালবাসে import *বা এটি অত্যধিক উপসর্গ (যা এই অনুশীলনটি প্রয়োগ করতে সহায়তা করে না) পছন্দ করে?

শক্ত কথার জন্য দুঃখিত, তবে এই দু'দিন ধরে আমি এই নির্বোধের মতো আচরণ করার চেষ্টা করছি ‑ আমি অন্য কোথাও ভুল না হলে পাইথনের মডেল প্যাকেজ এবং সাব-প্যাকেজগুলির মধ্যে কিছুটা সত্যিই ভেঙে গেছে এমন অনুভূতিটি আমাকে ছেড়ে দেবে।

মন্তব্য

  • আমি sys.pathবিশ্বব্যাপী পার্শ্ব প্রতিক্রিয়া এড়াতে বা *.pthফাইলগুলিতে নির্ভর করতে চাই না , যা sys.pathএকই বৈশ্বিক প্রভাবগুলির সাথে খেলতে পারা অন্য উপায় । সমাধানটি পরিষ্কার হওয়ার জন্য, এটি কেবল স্থানীয় হতে হবে। হয় পাইথন উপ-প্যাকেজ পরিচালনা করতে সক্ষম হয়, হয় তা নয়, তবে স্থানীয় স্টাফগুলি পরিচালনা করতে এটির জন্য বিশ্বব্যাপী কনফিগারেশন নিয়ে খেলতে হবে না।
  • আমি আমদানিগুলিও ব্যবহার করার চেষ্টা করেছি package/subpackage/__init__.py, তবে এটি কিছুই সমাধান করেনি, এটি একই কাজ করে এবং অভিযোগগুলি subpackageএকটি পরিচিত মডিউল নয়, যখন print subpackageবলে যে এটি একটি মডিউল (আবার অদ্ভুত আচরণ,)।

হতে পারে আমি পুরোপুরি ভুল শক্ত (বিকল্পটি আমি পছন্দ করব), তবে এটি পাইথন সম্পর্কে অনেক হতাশ বোধ করি।

তিনজনের পাশে আর কোন পরিচিত উপায় আমি চেষ্টা করেছি? এমন কিছু যা আমি জানি না?

(দীর্ঘশ্বাস)

-----% <----- সম্পাদনা ----->% -----

এখন পর্যন্ত উপসংহার (জনগণের মন্তব্যের পরে)

পাইথনে রিয়েল সাব-প্যাকেজের মতো কিছুই নেই, কারণ সমস্ত প্যাকেজ রেফারেন্স বিশ্বব্যাপী ডিকশনারিতে যায়, কেবল যার অর্থ কোনও স্থানীয় অভিধান নেই, যা বোঝায় যে স্থানীয় প্যাকেজ রেফারেন্স পরিচালনা করার কোনও উপায় নেই।

আপনাকে হয় পুরো উপসর্গ বা সংক্ষিপ্ত উপসর্গ বা উপনাম ব্যবহার করতে হবে। হিসাবে:

সম্পূর্ণ উপসর্গ সংস্করণ

from package.subpackage.module import attribute1
# An repeat it again an again
# But after that, you can simply:
use_of (attribute1)

সংক্ষিপ্ত উপসর্গ সংস্করণ (তবে পুনরাবৃত্তি উপসর্গ)

from package.subpackage import module
# Short but then you have to do:
use_of (module.attribute1)
# and repeat the prefix at every use place

বা অন্যথায়, উপরের একটি প্রকরণ।

from package.subpackage import module as m
use_of (m.attribute1)
# `m` is a shorter prefix, but you could as well
# define a more meaningful name after the context

কারখানা সংস্করণ

আপনি যদি কোনও ব্যাচে একবারে একাধিক সত্তা আমদানি করতে আপত্তি করেন না তবে আপনি এটি করতে পারেন:

from package.subpackage.module import attribute1, attribute2
# and etc.

আমার প্রথম পছন্দসই স্বাদে নয় (আমি আমদানি করা সত্তার প্রতি এক আমদানির বিবৃতি দিতে পছন্দ করি), তবে ব্যক্তিগতভাবে আমি এটির পক্ষে পছন্দ করব।

আপডেট (2012-09-14):

লেআউট সম্পর্কে একটি মন্তব্য বাদে অবশেষে অনুশীলনে ঠিক আছে বলে মনে হয়। উপরের পরিবর্তে, আমি ব্যবহার করেছি:

from package.subpackage.module import (

    attribute1, 
    attribute2,
    attribute3,
    ...)  # and etc.

আপনি যখন "থেকে। / আমদানি মডিউল" "/package/subpackage/__init__.py" এ লিখেন তখন কীভাবে চলছে?
মার্কাস আনটারওয়াদিজিটর

আপনার "অনুষঙ্গ সংস্করণ" আপনি যা করতে চান তার জন্য ঠিক সঠিক বলে মনে হচ্ছে। যদি আপনি অ্যাট্রিবিউট 1 এবং অ্যাট্রিবিউট 2 এর জন্য পৃথক আমদানি লাইন করেন (যেমন আপনি "পছন্দ করেন") তবে আপনি ইচ্ছাকৃতভাবে নিজেকে আরও কাজ দিচ্ছেন। এটি করার কোনও কারণ নেই।
ব্রেণবার্ন

দুঃখিত তবে আপনি যা চান তা আমি পাই না। আপনি কি আরও স্পষ্টভাবে আপনার প্রশ্নটির পুনঃব্যবস্থা করতে পারেন? আপনি ঠিক কি করতে চান? মানে, আপনি কী লিখতে চান যা কার্যকর হয় না এবং আপনি এটি কীভাবে কাজ করবেন বলে আশা করবেন? আমি যা পড়েছি তার দ্বারা আমি আপনাকে ভাবি যে আমদানির শব্দার্থতাকে জাভা বা সি এর অন্তর্ভুক্ত হতে পারে maybe শেষ কথা: আপনি একটি মডিউল "স্টার-ইম্পোর্ট" নিরাপদ করে একটি __all__ভেরিয়েবল যুক্ত করে নিরাপদে তৈরি করতে পারেন যার মধ্যে নামের তালিকা রয়েছে যা তারকা-আমদানির সময় রফতানি করা উচিত। সম্পাদনা করুন: ঠিক আছে, ব্রেইনবার্নের উত্তরটি পড়ে আমি বুঝছিলাম আপনি কী বোঝাতে চেয়েছিলেন।
বাকুরিউ

উত্তর:


68

আপনি importমডিউলগুলির জন্য অনুসন্ধানগুলি কীভাবে ভুল বোঝাবুঝি করছেন বলে মনে হচ্ছে । আপনি যখন কোনও আমদানি বিবৃতি ব্যবহার করেন এটি সর্বদা প্রকৃত মডিউল পথ (এবং / অথবা sys.modules) অনুসন্ধান করে; এটি পূর্ববর্তী আমদানির কারণে স্থানীয় নেমস্পেসে মডিউল অবজেক্টগুলির ব্যবহার করে না । যখন তুমি কর:

import package.subpackage.module
from package.subpackage import module
from module import attribute1

দ্বিতীয় লাইনটি প্যাকেজ নামে পরিচিত প্যাকেজটির সন্ধান করে package.subpackageএবং moduleসেই প্যাকেজটি থেকে আমদানি করে। এই রেখার তৃতীয় লাইনে কোনও প্রভাব নেই। তৃতীয় লাইনটি কেবল একটি মডিউল নামে পরিচিত moduleএবং এটির সন্ধান করে না। moduleআপনি উপরের লাইনটি থেকে পেয়েছেন এমন বস্তুটি এটি "পুনরায় ব্যবহার" করে না ।

অন্য কথায় from someModule import ...এটির অর্থ হ'ল "সামুদ্রিক নামক মডিউলটি যা আমি আগে আমদানি করেছিলাম ..." এর অর্থ "স্যাম.প্যাথে আপনি যে সন্ধান পেয়েছেন এমন কোনও মডুলুল নামক মডিউল থেকে ..."। প্যাকেজগুলি যেগুলি আমদানি করে সেগুলি আমদানির মাধ্যমে মডিউলের পথটি "বাড়িয়ে তোলা" করার কোনও উপায় নেই। আমদানি করার সময় আপনাকে সর্বদা পুরো মডিউলটির নাম উল্লেখ করতে হবে।

আপনি কী অর্জন করতে চাইছেন তা পরিষ্কার নয়। আপনি যদি কেবল নির্দিষ্ট অবজেক্ট অ্যাট্রিবিউট 1 আমদানি করতে চান তবে কেবল এটি করুন from package.subpackage.module import attribute1এবং এটি দিয়ে করুন। আপনি package.subpackage.moduleযে নামটি চান তা থেকে একবার আমদানি করার জন্য আপনাকে কখনই উদ্বিগ্ন হওয়ার দরকার নেই ।

আপনি যদি না অন্য নাম পরে অ্যাক্সেস করতে মডিউল এক্সেস আছে চান, তাহলে আপনি কি করতে পারেন from package.subpackage import moduleএবং, আপনি দেখা করেছি তারপর আপনি কি করতে পারেন module.attribute1এবং তাই হিসাবে আপনি চান হিসাবে অনেক।

আপনি উভয়ই চাইলে --- এটি হ'ল যদি আপনি attribute1সরাসরি অ্যাক্সেসযোগ্য চান এবং আপনি moduleঅ্যাক্সেসযোগ্য চান তবে উপরের দুটিটিই করুন:

from package.subpackage import module
from package.subpackage.module import attribute1
attribute1 # works
module.someOtherAttribute # also works

আপনি যদি package.subpackageএমনকি দু'বার টাইপ করা পছন্দ করেন না, আপনি কেবল অ্যাট্রিবিউট 1 এর জন্য স্থানীয়ভাবে একটি রেফারেন্স তৈরি করতে পারেন:

from package.subpackage import module
attribute1 = module.attribute1
attribute1 # works
module.someOtherAttribute #also works

আপনার মন্তব্যগুলি ইগনাসিও ওয়াজকেজ-আব্রামের (আমি তার বার্তাটি মন্তব্য করেছি) এর মত একই দিকে চলে গেছে। আপনি সর্বশেষে যোগ করুন, ব্যবহার module.attribute1সম্পর্কে আমার সম্পর্কে যদিও কিছু, তবে আমি যদিও সর্বত্র একটি উপসর্গের প্রয়োজনীয়তা এড়াতে চাই way সুতরাং আমাকে হয় প্রতি যেখানেই একটি উপসর্গ ব্যবহার করতে হবে, বা একটি স্থানীয় নাম ব্যবহার করে নামটি পুনরাবৃত্তি করতে হবে। আমি যে শৈলীর প্রত্যাশা করছিলাম তা নয়, তবে যদি কোনও উপায় না থাকে (সর্বোপরি, আমি আদাকে অভ্যস্ত, যার নাম পরিবর্তনের ঘোষণার সাথে অনুরূপ কিছু প্রয়োজন)।
Hibou57

@ হিবিউ ৫7: আপনি আপনার "সংস্করণ ২" তে কী অর্জন করতে চাইছেন তা এখনও আমার কাছে পরিষ্কার নয়। আপনি কী করতে চান তা সম্ভব নয়? আপনি প্যাকেজ / মডিউল / বৈশিষ্ট্য নামের কোনও অংশ পুনরায় টাইপ করতে চান না, তবে এখনও মডিউল এবং এর বৈশিষ্ট্য উভয়ই আমদানি করতে চান?
ব্রেণবার্ন

আমি যেমন স্থানীয় প্যাকেজ রেফারেন্স পেতে পারি ঠিক তেমনই একটি স্থানীয় প্যাকেজ রেফারেন্সও আমি চেয়েছিলাম। দেখে মনে হচ্ছে অবশেষে স্থানীয় স্থানীয় মডিউল রেফারেন্স রয়েছে তবে আপনি এগুলি থেকে আমদানি করতে পারবেন না। এটি একটি মজাদার স্বাদের সাথে স্থানীয় এবং বৈশ্বিকের মিশ্রণ রয়েছে (কিছু স্টাফ স্থানীয় হতে পারে, কিছু অন্যকে অবশ্যই বিশ্বব্যাপী হতে হবে, আমি এটি পছন্দ করি না, তবে আমি ঠিক আছি যতক্ষণ না এখন এটি কীভাবে কাজ করে তা আরও ভালভাবে বুঝতে পারি)। আপনার বার্তার জন্য ধন্যবাদ।
Hibou57

4
আমি নিশ্চিত না যে আপনি এখনও বুঝতে পারেন যে এটি কীভাবে কাজ করে। বা যে আপনি যে কোনও ক্ষেত্রে 2012 সালে করেছেন।
হেজাজমান

4
আমি যখনই 6 মাসের ছাঁটাইয়ের পরে পাইথনে ফিরে আসি, আমি এখানেই শেষ করি। যদি আমি এই পৃষ্ঠায় প্রতিবার ভিজিট করতে পারি তবে কেবল যদি আমি উজ্জীবিত হতে পারি! আমি এই বাক্যটি দিয়ে একটি বিশাল পোস্টার তৈরি করতে যাচ্ছি: "প্যাকেজগুলি যেগুলি আমদানি করে সেগুলি আমদানি করে মডিউলটির" বর্ধিতভাবে "তৈরি করার কোনও উপায় নেই"
প্যাট্রিকটি

10

# 2 ব্যর্থ হওয়ার কারণ হ'ল sys.modules['module']অস্তিত্ব নেই (আমদানির রুটিনটির নিজস্ব সুযোগ রয়েছে, এবং moduleস্থানীয় নামটি দেখতে পাচ্ছেন না ) এবং moduleঅন-ডিস্কে কোনও মডিউল বা প্যাকেজ নেই । নোট করুন যে আপনি কমা দ্বারা একাধিক আমদানি করা নাম আলাদা করতে পারেন।

from package.subpackage.module import attribute1, attribute2, attribute3

এছাড়াও:

from package.subpackage import module
print module.attribute1

আপনার রেফারেন্স sys.modules['name']যা আমি এখনও অবধি জানি না, সেটাই আমাকে ভাবিয়ে তুলেছিল যে আমি যা ভয় পেয়েছিলাম (এবং ব্রেনবার্ন নিশ্চিত করে): পাইথনের আসল সাব-প্যাকেজগুলির মতো কিছুই নেই। sys.modules, যেমন এর নামটি বোঝায়, এটি বিশ্বব্যাপী, এবং মডিউলগুলির সমস্ত রেফারেন্স যদি এটির উপর নির্ভর করে তবে মডিউলের স্থানীয় রেফারেন্সের মতো কিছুই নেই (পাইথন ৩.x এর সাথে আসতে পারে?)।
Hibou57

আপনার "রেফারেন্স" এর ব্যবহারটি অস্পষ্ট; import# 2 এ প্রথমটি package.subpackage.moduleআবদ্ধ হতে একটি স্থানীয় রেফারেন্স উত্পন্ন করে module
Ignacio Vazquez-Abrams

হ্যাঁ, তবে এটি একটি "মডিউল" আমি ;-) থেকে আমদানি করতে পারি না
Hibou57

0

আপনি যা করার চেষ্টা করছেন তা হ'ল যদি আপনার বিশ্বব্যাপী নেমস্পেসে অ্যাট্রিবিউট 1 পাওয়া যায় তবে 3 সংস্করণটি ঠিক আছে। কেন এটি ওভারকিল উপসর্গ?

সংস্করণ 2 এ, পরিবর্তে

from module import attribute1

আপনি করতে পারেন

attribute1 = module.attribute1

attribute1 = module.attribute1কোনও অতিরিক্ত মূল্য ছাড়াই কেবল নামটি পুনরাবৃত্তি করছে। আমি জানি এটি কার্যকর হয় তবে আমি এই স্টাইলটি পছন্দ করি না (যা বোঝায় না যে আমি আপনার উত্তরটি পছন্দ করি না)।
Hibou57

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