파일 사이에 전역 변수를 사용합니까?


208

전역 변수가 어떻게 작동하는지 혼란 스럽습니다. 약 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 writing 또는 pickle을 사용하지 않고 어떻게 해야할지 생각할 수 없습니다. 하고 싶지 않아요


사실, 두 번째 접근 방식은 나에게 잘 작동합니다. main.py는 "hey"를 올바르게 출력합니다. "작동하지 않았다"는 당신이 무엇인지 더 구체적으로 설명해 주시겠습니까?
rodion

@rodion : importing cycles-서브 파일의 코드는 globfile을 가져 오려고 시도합니다.이 파일은 본문을 다시 가져옵니다.
jsbueno

1
NameError: name 'myList' is not defined에서 main.py라인print(globfile.myList[0])

답변:


319

문제는 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(). 모듈은 처음 가져올 때만 평가되므로 모듈 본문에서 해당 변수를 초기화해도됩니다.
Kirk Strauser

19
+1 Kirk : 동의합니다. 그러나 내 접근 방식은 주 프로그램이 시작되기 전에 다른 모듈이 globals.myList를 수정하는 경우를 방지합니다.
Hai Vu

2
내장 이름 인 전역이 아닌 다른 이름으로 부릅니다. PyLint는 다음과 같이 경고합니다 : "내장 '전역'재정의 (재정의 내장)"
twasbrillig

감사. 이 파일 구조를 사용하여 Eclipse PyDev에 나타나는 "가져 오기에서 정의되지 않은 변수"오류를 제거하는 방법에 대한 아이디어가 있습니까 (예 : settings.py에서 전역 변수 가져 오기)? PyDev에서 오류비활성화 해야했지만 이상적이지 않습니다.
Franck Dernoncourt

@FranckDernoncourt 죄송합니다. Eclipse를 사용하지 않으므로 귀하보다 더 실마리가 없습니다.
Hai Vu

94

모듈 간 전역 변수 공유 에 대한 Python의 문서를 참조하십시오 .

단일 프로그램 내에서 모듈간에 정보를 공유 할 수있는 일반적인 방법은 특수 모듈 (종종 config 또는 cfg)을 작성하는 것입니다.

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 import * 에서 사용하지 마십시오 . 그렇게하면 수입자의 네임 스페이스가 어수선 해져서 ​​린터가 정의되지 않은 이름을 감지하기가 훨씬 어려워집니다.


1
생명의 은인-그 링크 만!
toonarmycaptain

4
이것은 받아 들인 대답보다 더 깨끗한 접근법처럼 보입니다.
JoeyC

2
사용자가 설정할 수 없습니다 x사용하는 from config import x경우에만 사용import config
Yariv

1
가장 간단한 해결책! 감사합니다
user1297406

22

파이썬 전역 변수를 "모듈"변수라고 생각하면 C의 전통적인 "전역 변수"보다 훨씬 유용합니다.

전역 변수는 실제로 모듈에 정의되며 해당 모듈 __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
와우, 일반적으로 서로 가져 오는 두 파일이 무한 루프로 들어갈 것으로 예상합니다.
Nikhil VJ

2
ha 언뜻 보면 그렇게 보이지 않습니까? def stuff ()에서 발생하는 것은 파일이로드 될 때 가져 오기가 실행되지 않는다는 것입니다. stuff () 함수가 호출 될 때만 실행됩니다. 따라서 main으로 시작하여 하위 파일을 가져온 다음 subfile.stuff ()를 호출하여 main ... no 루프를 가져옵니다. main에서 한 번만 가져옵니다. 가져 오기주기에 대해서는 subfile.py 예제의 참고 사항을 참조하십시오.
John

11

를 사용 from your_file import *하면 문제가 해결됩니다. 가져 오기에서 로컬 변수를 제외하고 전 세계에서 사용할 수 있도록 모든 것을 정의합니다.

예를 들면 다음과 같습니다.

##test.py:

from pytest import *

print hello_world

과:

##pytest.py

hello_world="hello world!"

4
그러한 변수 중 하나에 할당하는 경우를 제외하고
jsbueno

5
나는 개인적 import *으로 모든 비용을 사용 하지 말고 참조가 명백하고 혼란스럽지 않게한다. 게다가 *어떤 모듈에서 " "참조 를 실제로 사용한 적이 있는가?
ThorSummoner

19
가져 오지 마십시오 *. 전역 변수는 더 이상 동기화되지 않습니다. 각 모듈은 자체 사본을받습니다. 한 파일에서 변수를 변경하면 다른 파일에 반영되지 않습니다. 또한 docs.python.org/2/faq/
Isa Hassen

8

Hai Vu 답변은 한 가지 의견만으로도 효과적입니다.

다른 모듈에서 전역을 사용하고 전역을 동적으로 설정하려는 경우 전역 변수를 설정 한 후 다른 모듈을 가져 오려면 다음과 같이주의하십시오.

# 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는 서브 파일이 아닌 globfile의 속성입니다. 이것은 당신이 원하는대로 작동합니다.

마이크

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.