फ़ाइलों के बीच वैश्विक चर का उपयोग करना?


207

मैं थोड़ा भ्रमित हूं कि वैश्विक चर कैसे काम करते हैं। मेरे पास एक बड़ी परियोजना है, जिसमें लगभग 50 फाइलें हैं, और मुझे उन सभी फाइलों के लिए वैश्विक चर को परिभाषित करने की आवश्यकता है।

मैंने जो कुछ भी किया, उसे अपनी परियोजनाओं की main.pyफ़ाइल में परिभाषित किया , जो निम्नानुसार है:

# ../myproject/main.py

# Define global myList
global myList
myList = []

# Imports
import subfile

# Do something
subfile.stuff()
print(myList[0])

मैं निम्नलिखित के रूप myListमें उपयोग करने की कोशिश कर रहा हूंsubfile.py

# ../myproject/subfile.py

# Save "hey" into myList
def stuff():
    globals()["myList"].append("hey")

एक और तरीका मैंने कोशिश की, लेकिन काम नहीं किया

# ../myproject/main.py

# Import globfile    
import globfile

# Save myList into globfile
globfile.myList = []

# Import subfile
import subfile

# Do something
subfile.stuff()
print(globfile.myList[0])

और subfile.pyमेरे अंदर यह था:

# ../myproject/subfile.py

# Import globfile
import globfile

# Save "hey" into myList
def stuff():
    globfile.myList.append("hey")

लेकिन फिर, यह काम नहीं किया। मुझे इसे कैसे लागू करना चाहिए? मैं समझता हूं कि यह उस तरह से काम नहीं कर सकता है, जब दो फाइलें वास्तव में एक-दूसरे को नहीं जानती हैं (अच्छी तरह से सबफाइल मुख्य नहीं जानता है), लेकिन मैं यह नहीं सोच सकता कि इसे कैसे करना है, बिना io लेखन या अचार का उपयोग किए बिना, जो मैं नहीं करना चाहता।


दरअसल, आपका दूसरा तरीका मेरे लिए ठीक काम करता है। main.py सही ढंग से प्रिंट करता है "हे"। क्या आप मेरे द्वारा "यह काम नहीं किया" पर अधिक विशिष्ट हो सकते हैं?
रात्रि

@ क्रोध: आयात चक्र - सबफ़ाइल में कोड ग्लॉफ़ाइल आयात करने की कोशिश करता है, जो कि शरीर में स्वयं आयात करता है
jsbueno

1
NameError: name 'myList' is not definedसे main.pyलाइनprint(globfile.myList[0])

जवाबों:


318

समस्या आप से परिभाषित myListहै main.py, लेकिन subfile.pyइसका उपयोग करने की आवश्यकता है। इस समस्या को हल करने का एक साफ तरीका यहां है: सभी ग्लोबल्स को एक फाइल में स्थानांतरित करें, मैं इस फाइल को कॉल करता हूं settings.py। यह फाइल ग्लोबल्स को परिभाषित करने और उन्हें आरंभ करने के लिए जिम्मेदार है:

# settings.py

def init():
    global myList
    myList = []

अगला, आप subfileग्लोबल्स आयात कर सकते हैं:

# subfile.py

import settings

def stuff():
    settings.myList.append('hey')

ध्यान दें कि subfileकॉल नहीं है init()- वह कार्य main.pyनिम्न के अंतर्गत आता है :

# main.py

import settings
import subfile

settings.init()          # Call only once
subfile.stuff()         # Do stuff with global var
print settings.myList[0] # Check the result

इस तरह, आप अपने उद्देश्य को प्राप्त करते हैं जबकि वैश्विक चर को एक से अधिक बार आरंभ करने से बचते हैं।


40
मुझे सामान्य दृष्टिकोण पसंद है, लेकिन पूरे init()सामान को नहीं। मॉड्यूल का केवल पहली बार आयात होने पर मूल्यांकन किया जाता है, इसलिए मॉड्यूल के शरीर में उन चरों को प्रारंभ करना ठीक है।
कर्क स्ट्रूसर

19
+1 कर्क: मैं सहमत हूं। हालांकि, मेरा दृष्टिकोण उस मामले को रोकता है जहां मुख्य कार्यक्रम शुरू होने से पहले अन्य मॉड्यूल globals.myList को संशोधित करते हैं।
हाई वु

2
आपको इसे ग्लोबल्स के अलावा कुछ और कहना चाहिए, जो एक बिलिन नाम है। PyLint चेतावनी देता है: "अंतर्निहित ग्लोबल्स को पुनर्परिभाषित करना (पुनर्परिभाषित-निर्मित)"
ट्वासब्रिलिग

धन्यवाद। इस फ़ाइल संरचना (यानी सेटिंग से वैश्विक वैरिएबल आयात करके) ग्रहण PyDev में दिखाई देने वाली "आयात से अपरिभाषित चर" त्रुटियों को दूर करने का कोई भी विचार? मुझे PyDev में त्रुटि को अक्षम करना पड़ा , जो आदर्श नहीं है।
फ्रेंक डर्नोनकोर्ट

@FranckDernoncourt मुझे खेद है, मैं एक्लिप्स का उपयोग नहीं करता हूं इसलिए मैं आपसे ज्यादा क्लूलेस हूं।
हाई

93

मॉड्यूल भर में वैश्विक चर साझा करने पर अजगर का दस्तावेज़ देखें :

एकल प्रोग्राम के भीतर मॉड्यूल को जानकारी साझा करने का विहित तरीका एक विशेष मॉड्यूल (जिसे अक्सर कॉन्फ़िगरेशन या सीएफजी कहा जाता है) बनाना है।

config.py:

x = 0   # Default value of the 'x' configuration setting

अपने एप्लिकेशन के सभी मॉड्यूलों में कॉन्फ़िगरेशन मॉड्यूल आयात करें; मॉड्यूल तब वैश्विक नाम के रूप में उपलब्ध हो जाता है।

main.py:

import config
print (config.x)

या

from config import x
print (x)

सामान्य तौर पर, modulename आयात * से उपयोग न करें । ऐसा करने से आयातक के नाम स्थान पर कब्जा कर लिया जाता है, और इससे अनिर्णायक नामों का पता लगाना मुश्किल हो जाता है।


1
लाइफसेवर - बस उस लिंक के लिए!
अक्टूबर तक टूनार्माइकैप करें

4
यह स्वीकृत उत्तर की तुलना में एक क्लीनर दृष्टिकोण की तरह लगता है।
जॉयसी

2
ध्यान दें कि आप xका उपयोग करके सेट नहीं किया जा सकता है from config import x, केवल का उपयोग करimport config
यारिव

1
सरलतम उपाय! धन्यवाद
user1297406

22

आप पायथन वैश्विक चर को "मॉड्यूल" चर के रूप में सोच सकते हैं - और जैसे कि वे सी से पारंपरिक "वैश्विक चर" की तुलना में बहुत अधिक उपयोगी हैं।

एक वैश्विक चर वास्तव में एक मॉड्यूल में परिभाषित किया गया है __dict__और उस मॉड्यूल के बाहर से एक मॉड्यूल विशेषता के रूप में पहुँचा जा सकता है।

तो, आपके उदाहरण में:

# ../myproject/main.py

# Define global myList
# global myList  - there is no "global" declaration at module level. Just inside
# function and methods
myList = []

# Imports
import subfile

# Do something
subfile.stuff()
print(myList[0])

तथा:

# ../myproject/subfile.py

# Save "hey" into myList
def stuff():
     # You have to make the module main available for the 
     # code here.
     # Placing the import inside the function body will
     # usually avoid import cycles - 
     # unless you happen to call this function from 
     # either main or subfile's body (i.e. not from inside a function or method)
     import main
     main.mylist.append("hey")

1
वाह, आम तौर पर एक दो फ़ाइलों को एक दूसरे को आयात करने की उम्मीद होगी अनंत लूप में।
निखिल वीजे

2
हा पहली नज़र में यह इस तरह दिखता है, है ना? डीफ़ स्टफ () में क्या होता है कि फ़ाइल लोड होने पर आयात नहीं चलता है। यह केवल तब चलता है जब सामान () फ़ंक्शन को कहा जाता है। तो मुख्य के साथ शुरू हम सबफ़ाइल आयात करते हैं और फिर सबफ़ाइल.स्टफ़ () कहते हैं जो तब मुख्य आयात करता है ... कोई लूप नहीं, बस मुख्य में एक बार आयात करें। आयात चक्रों के बारे में सबफ़िल्मोइद उदाहरण में नोट देखें।
जॉन

11

का उपयोग from your_file import *कर अपनी समस्याओं को ठीक करना चाहिए। यह सब कुछ परिभाषित करता है ताकि यह विश्व स्तर पर उपलब्ध हो (पाठ्यक्रम के आयात में स्थानीय चर के अपवाद के साथ)।

उदाहरण के लिए:

##test.py:

from pytest import *

print hello_world

तथा:

##pytest.py

hello_world="hello world!"

4
सिवाय इसके कि अगर आप ऐसे किसी एक चर
jsbueno

5
मैं व्यक्तिगत रूप से import *हर कीमत पर उपयोग से बचता हूं ताकि संदर्भ स्पष्ट (और भ्रमित न हों), इसके अलावा, जब आपने कभी *किसी मॉड्यूल में सभी " " संदर्भों का वास्तव में उपयोग किया हो ?
थोरसुमोनर

19
न करें * आयात करें। आपके वैश्विक चर अब सिंक में नहीं रहेंगे। प्रत्येक मॉड्यूल अपनी प्रति प्राप्त करता है। चर को एक फ़ाइल में बदलना दूसरे में प्रतिबिंबित नहीं होगा। इसे docs.python.org/2/faq/… के
ईसा हसन

8

हाई वू जवाब महान काम करता है, सिर्फ एक टिप्पणी:

यदि आप अन्य मॉड्यूल में वैश्विक उपयोग कर रहे हैं और आप वैश्विक रूप से सेट करना चाहते हैं, तो उदाहरण के लिए, वैश्विक चर सेट करने के बाद अन्य मॉड्यूल आयात करने पर ध्यान दें:

# settings.py
def init(arg):
    global myList
    myList = []
    mylist.append(arg)


# subfile.py
import settings

def print():
    settings.myList[0]


# main.py
import settings
settings.init("1st")     # global init before used in other imported modules
                         # Or else they will be undefined

import subfile    
subfile.print()          # global usage

4

आपका दूसरा प्रयास पूरी तरह से काम करेगा, और वास्तव में चर नामों को संभालने का एक अच्छा तरीका है जिसे आप विश्व स्तर पर उपलब्ध कराना चाहते हैं। लेकिन आपके पास अंतिम पंक्ति में एक नाम त्रुटि है। यहां बताया गया है कि यह कैसा होना चाहिए:

# ../myproject/main.py

# Import globfile    
import globfile

# Save myList into globfile
globfile.myList = []

# Import subfile
import subfile

# Do something
subfile.stuff()
print(globfile.myList[0])

अंतिम पंक्ति देखें? myList ग्लॉफाइल का एक attr है, सबफाइल नहीं। यह आप की इच्छानुसार काम करेगा।

माइक

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.