আমদানি করা মডিউলগুলিতে বিশ্বব্যাপী ভেরিয়েবলের দৃশ্যমানতা


111

আমি পাইথন স্ক্রিপ্টে একটি প্রাচীর আমদানি করে মডিউলগুলির একটি অংশে চলে এসেছি। আমি ত্রুটিটি বর্ণনা করার জন্য যথাসাধ্য চেষ্টা করব, আমি কেন এটি চালাচ্ছি এবং কেন আমার সমস্যা সমাধানের জন্য আমি এই বিশেষ পদ্ধতির সাথে বেঁধে দিচ্ছি (যা আমি একটি সেকেন্ডে বর্ণনা করব):

ধরা যাক আমার কাছে একটি মডিউল আছে যাতে আমি কিছু ইউটিলিটি ফাংশন / ক্লাস সংজ্ঞায়িত করেছি, যা নামস্থানে সংজ্ঞায়িত সংস্থাগুলি উল্লেখ করে যেখানে এই সহায়ক মডিউলটি আমদানি করা হবে (আসুন "একটি" যেমন একটি সত্তা হয়ে উঠুক):

মডিউল 1:

def f():
    print a

এবং তারপরে আমার কাছে প্রধান প্রোগ্রাম রয়েছে, যেখানে "এ" সংজ্ঞায়িত করা হয়েছে, যার মধ্যে আমি সেইগুলি ইউটিলিটিগুলি আমদানি করতে চাই:

import module1
a=3
module1.f()

প্রোগ্রামটি কার্যকর করা নিম্নলিখিত ত্রুটিটিকে ট্রিগার করবে:

Traceback (most recent call last):
  File "Z:\Python\main.py", line 10, in <module>
    module1.f()
  File "Z:\Python\module1.py", line 3, in f
    print a
NameError: global name 'a' is not defined

অতীতে অনুরূপ প্রশ্ন জিজ্ঞাসা করা হয়েছিল (দু'দিন আগে, ডিউহ) এবং বেশ কয়েকটি সমাধান প্রস্তাব দেওয়া হয়েছে, তবে আমি সত্যিই মনে করি না যে এগুলি আমার প্রয়োজনীয়তার সাথে খাপ খায়। এখানে আমার বিশেষ প্রসঙ্গ:

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

শেষ ফলাফলটি এরকম কিছু হবে:

utilities_module.py:

def utility_1(args):
    code which references a variable named "cur"
def utility_n(args):
    etcetera

এবং আমার প্রধান মডিউল:

program.py:

import MySQLdb, Tkinter
db=MySQLdb.connect(#blahblah) ; cur=db.cursor()  #cur is defined!
from utilities_module import *

এবং তারপরে, আমি যে কোনও ইউটিলিটি ফাংশনকে কল করার চেষ্টা করার সাথে সাথে এটি উল্লিখিত "গ্লোবাল নাম সংজ্ঞায়িত নয়" ত্রুটিটিকে ট্রিগার করে।

একটি বিশেষ পরামর্শ ছিল ইউটিলিটি ফাইলে "প্রোগ্রাম ইম্পোর্ট কার্" বিবৃতি থাকা যেমন:

utilities_module.py:

from program import cur
#rest of function definitions

program.py:

import Tkinter, MySQLdb
db=MySQLdb.connect(#blahblah) ; cur=db.cursor()  #cur is defined!
from utilities_module import *

তবে এটি চক্রীয় আমদানি বা এর মতো কিছু এবং নীচে লাইন, এটি ক্র্যাশও হয়। সুতরাং আমার প্রশ্নটি হ'ল:

প্রধান মডিউলে সংজ্ঞায়িত "কার" অবজেক্টটি কীভাবে আমি জাহাজে তৈরি করতে পারি, এটিতে আমদানি করা সহায়ক সহায়ক ফাংশনগুলির জন্য দৃশ্যমান?

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


1
আপনার আপডেটের ভিত্তিতে: আপনি সম্ভবত কোনও একক ভাগ করা কার্সার চান না। একটি একক ভাগ করা সংযোগ , হ্যাঁ, তবে কার্সারগুলি সস্তা, এবং একইসাথে একাধিক কার্সার বেঁচে থাকার জন্য অনেকগুলি ভাল কারণ থাকতে পারে (উদাহরণস্বরূপ, আপনি লকস্টেপে তাদের দুটি মাধ্যমে পুনরাবৃত্তি করতে পারেন fetch_allএবং পরিবর্তে দুটি তালিকার মাধ্যমে পুনরাবৃত্তি করতে পারেন) , বা ঠিক তাই আপনার দুটি ভিন্ন থ্রেড / গ্রিনলেট / কলব্যাক-চেইন / কোনও দ্বন্দ্ব ছাড়াই ডাটাবেস ব্যবহার করা যায়)।
abarnert

যাই হোক, যাই হোক না কেন আপনি শেয়ার করতে চান, আমি মনে করি উত্তর এখানে সরানো হয় db(এবং curএকটি পৃথক মডিউল উভয় যে মধ্যে যদি জিদ,) programএবং utilities_moduleথেকে এটা আমদানি করুন। এইভাবে আপনি বিজ্ঞপ্তি নির্ভরতা (প্রোগ্রামটি আমদানি করে মডিউলগুলি থেকে প্রোগ্রাম আমদানি করে) এবং তাদের সাথে যে বিভ্রান্তি আসে তা পান না get
abarnert

উত্তর:


243

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

আপনার প্রকৃত ব্যবহারের ক্ষেত্রে নির্ভর করে এটি সমাধানের বিভিন্ন উপায় রয়েছে।


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

import module1
thingy1 = module1.Thingy(a=3)
thingy1.f()

আপনি যদি সত্যিই কোনও বিশ্বব্যাপী চান তবে এটি ব্যবহারের জন্য কেবল সেখানে module1, এটি মডিউলটিতে সেট করুন।

import module1
module1.a=3
module1.f()

অন্যদিকে, যদি aপুরো অনেকগুলি মডিউল ভাগ করে নেওয়া হয় তবে এটিকে অন্য কোথাও রেখে দিন এবং সবাইকে এটি আমদানি করতে বলুন:

import shared_stuff
import module1
shared_stuff.a = 3
module1.f()

… এবং, মডিউল 1.py এ:

import shared_stuff
def f():
    print shared_stuff.a

fromভেরিয়েবলটি ধ্রুবক হিসাবে অভিযুক্ত না হওয়া পর্যন্ত আমদানি ব্যবহার করবেন না । আমদানির সময় যা কিছু উল্লেখ করা হয়েছিল তাতে প্রাথমিকভাবে from shared_stuff import aএকটি নতুন aপরিবর্তনশীল তৈরি করবে shared_stuff.aএবং এই নতুন aভেরিয়েবলটি অ্যাসাইনমেন্টের দ্বারা প্রভাবিত হবে না shared_stuff.a


অথবা, বিরল ক্ষেত্রে আপনার কোনও বিল্টিনের মতো সর্বত্র সত্যই বৈশ্বিক হওয়া দরকার, এটি বিল্টিন মডিউলে যুক্ত করুন। পাইথন ২.x এবং ৩.x এর মধ্যে সঠিক বিশদ পৃথক fer 3.x এ, এটি এর মতো কাজ করে:

import builtins
import module1
builtins.a = 3
module1.f()

12
সুন্দর এবং ব্যাপক।
22:55 এ কিন্ডেল করুন

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

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

1
আপডেট: ধন্যবাদ! ভাগ করা_ স্টাফ পদ্ধতির কাজটি ঠিকঠাক হয়েছিল, এর সাথে আমি মনে করি আমি অন্য যে কোনও সমস্যা নিয়ে কাজ করতে পারি।
নুবার্কে

1
@ ড্যানিয়েল আর্মেনগোড: আপনার যদি সত্যিই প্রয়োজন না হয় তবে আমি অন্তর্নির্মিত উত্তরটি যুক্ত করেছি। (এবং আপনার যদি আরও বিশদ বিবরণ প্রয়োজন হয় তবে এসও অনুসন্ধান করুন; বিল্টিনগুলিতে কীভাবে জিনিসপত্র যুক্ত করতে হবে সে সম্পর্কে কমপক্ষে দুটি প্রশ্ন রয়েছে)) তবে, বাই রিকো যেমন বলেছেন, আপনার প্রায় অবশ্যই এটির প্রয়োজন নেই, বা এটি চান না।
abarnert

8

কার্যকারণ হিসাবে, আপনি বাইরের স্তরটিতে পরিবেশের ভেরিয়েবলগুলি সেট করার বিষয়টি বিবেচনা করতে পারেন।

main.py:

import os
os.environ['MYVAL'] = str(myintvariable)

mymodule.py:

import os

myval = None
if 'MYVAL' in os.environ:
    myval = os.environ['MYVAL']

অতিরিক্ত সতর্কতা হিসাবে, যখন মাইওয়ালটি মডিউলের ভিতরে সংজ্ঞায়িত না হয় তবে কেসটি হ্যান্ডেল করুন।


5

একটি ফাংশন মডিউল এটা সে সম্পর্কে globals ব্যবহার সংজ্ঞায়িত হবে। এর পরিবর্তে সেটিংয়ের a = 3, উদাহরণস্বরূপ, আপনি সেই সেটিংসটিকে হওয়া উচিত module1.a = 3। সুতরাং, যদি আপনি curগ্লোবাল ইন হিসাবে utilities_moduleসেট করতে চান , সেট করুন utilities_module.cur

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


'আমদানি মডিউল 1' লেখার পরিবর্তে, ব্যবহারকারী যদি 'মডিউল 1 আমদানি চ' থেকে লিখতেন, তবে চ মেন.পি এর বিশ্বব্যাপী নেমস্পেসে আসত f এখন মেইন.পি-তে যদি আমরা f () ব্যবহার করি, তবে যেহেতু a = 3 এবং f (ফাংশন সংজ্ঞা) উভয়ই মূলের গ্লোবাল নেমস্পেসে রয়েছে। এটি কি সমাধান? যদি আমি ভুল হয় তবে দয়া করে আপনি আমাকে এই বিষয়ে যে কোনও নিবন্ধের দিকে নির্দেশ করতে পারেন দয়া করে
পরিবর্তনশীল

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

5

এই পোস্টটি পাইথনের আচরণের মুখোমুখি হয়েছি is আপনি উপরে যে পরামর্শগুলি পড়েছেন সেগুলি আপনার পক্ষে কাজ করে না যদি আপনি নীচে একই জিনিসটি করেন।

যথা, আমার কাছে একটি মডিউল রয়েছে যা বৈশ্বিক / ভাগ করে নেওয়া ভেরিয়েবলগুলি (উপরে প্রস্তাবিত হিসাবে) রয়েছে:

#sharedstuff.py

globaltimes_randomnode=[]
globalist_randomnode=[]

তারপরে আমার কাছে প্রধান মডিউল ছিল যা এর সাথে ভাগ করা স্টাফগুলি আমদানি করে:

import sharedstuff as shared

এবং কিছু অন্যান্য মডিউল যা প্রকৃতপক্ষে এই অ্যারেগুলিকে জনপ্রিয় করেছে। এগুলিকে মূল মডিউল দ্বারা ডাকা হয়। এই অন্যান্য মডিউলগুলি প্রস্থান করার সময় আমি পরিষ্কারভাবে দেখতে পাচ্ছি যে অ্যারেগুলি জনবহুল। তবে এগুলি মূল মডিউলে ফেরার সময় সেগুলি খালি ছিল। এটি আমার জন্য বরং অদ্ভুত ছিল (ভাল, আমি পাইথনে নতুন) যাইহোক, আমি যখন মুড মডিউলটিতে শেয়ারড স্টাফ.পি আমদানির উপায়টি পরিবর্তন করি তখন:

from globals import *

এটি কাজ করেছিল (অ্যারেগুলি জনবহুল হয়েছিল)।

শুধু Sayin'


2

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

মডিউল 1:

cursor = None

def setCursor(cur):
    global cursor
    cursor = cur

def method(some, args):
    global cursor
    do_stuff(cursor, some, args)

মূল প্রোগ্রাম:

import module1

cursor = get_a_cursor()
module1.setCursor(cursor)
module1.method()

2

যেহেতু গ্লোবালগুলি মডিউল নির্দিষ্ট, আপনি সমস্ত আমদানি করা মডিউলগুলিতে নিম্নলিখিত ফাংশনটি যুক্ত করতে পারেন এবং তারপরে এটি ব্যবহার করতে পারেন:

  • তাদের জন্য গ্লোবাল হিসাবে একক ভেরিয়েবল (অভিধানের বিন্যাসে) যুক্ত করুন
  • এটিতে আপনার মূল মডিউল গ্লোবালগুলি স্থানান্তর করুন ।

অ্যাডগ্লোবালস = ল্যাম্বদা এক্স: গ্লোবাল ()। আপডেট (এক্স)

তারপরে বর্তমান গ্লোবালগুলিতে আপনাকে যা করতে হবে তা হ'ল:

আমদানি মডিউল

module.addglobals (globals ())


1

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

# external_module
def imported_function(global_dict=None):
    print(global_dict["a"])


# calling_module
a = 12
from external_module import imported_function
imported_function(global_dict=globals())

>>> 12

0

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

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