Python : 'from X import Y'로 가져온 컴포넌트 Y를 다시로드 하시겠습니까?


96

Python에서를 사용하여 인터프리터 세션에서 모듈 X를 가져 왔고 모듈 import X이 외부에서 변경되면 reload(X). 변경 사항은 통역 세션에서 사용할 수 있습니다.

.NET을 사용하여 모듈 X에서 구성 요소 Y를 가져올 때도 이것이 가능한지 궁금합니다 from X import Y.

reload YY는 모듈 자체가 아니라 모듈 내부의 구성 요소 (이 경우 클래스)이므로 문 이 작동하지 않습니다.

인터프리터 세션을 떠나지 않고 (또는 전체 모듈을 가져 오지 않고) 모듈의 개별 구성 요소를 다시로드 할 수 있습니까?

편집하다:

설명을 위해 질문은 모듈 X 에서 클래스 또는 함수 Y 를 가져오고 패키지 X에서 모듈 Y가 아닌 변경시 다시로드하는 것입니다.


나는이 질문에 모순이 있다고 믿는다 : " ... possible ... import a component Y from module X"vs " question is ... importing a class or function X from a module Y". 그 효과에 편집을 추가하고 있습니다.
Catskul 2012

표시된 답변은 실제로 질문에 대한 답변이 아닌 것 같습니다. 업데이트 / 댓글을 달 수 있습니까?
Catskul 2014 년

답변:


51

Y는 모듈 (그리고 X 패키지)하면 reload(Y)잘 될 것입니다 - (예 : 내 고용주의 등의) 좋은 파이썬 스타일 가이드가 말을 왜 그렇지 않으면, 당신이 볼 수 결코 수입 아무것도 를 제외하고 모듈이 많은 좋은 이유 중 하나를 밖으로 ( -그러나 사람들은 여전히 좋은 생각 이 아니라고 아무리 설명하더라도 함수와 클래스를 직접 가져옵니다 .-) .


1
너의 의도를 알 겠어. 좋은 생각이 아닌 다른 좋은 이유에 대해 자세히 설명 하시겠습니까?
cschol

6
@cschol : Zen of Python, 마지막 구절 ( import thisPython의 Zen을보기위한 대화식 프롬프트에서); 모든 이유 네임 스페이스는 모듈, 예측 가능하고 제어 일부 항목을 재정 의하여 유연하게 변경하기위한 경적을 울리고 좋은 생각 (이름의이 조회되는 것을 즉시 현지 시각 단서, 조롱의 용이성 / 시험에서 주입, 다시로드 할 수있는 능력, 능력입니다 데이터의 직렬화 및 복구에 대한 동작 [[예 : 산세 및 산세 제거]] 등-SO 주석은이 풍부하고 긴 주장을 정당화하기에 충분하지 않습니다 !!!-)
Alex Martelli

4
Python 3에서 reload는 더 이상 기본 네임 스페이스에 없지만 importlib패키지 로 이동되었습니다 . importlib.reload(Y) docs.python.org/3.4/library/...는 참조 stackoverflow.com/questions/961162/...
파리

4
@ThorSummoner는 절대 아닙니다. "항상 모듈 가져 오기"를 의미하므로 "my.package import mymodule에서"는 절대적으로 괜찮고 실제로 선호됩니다. 클래스, 함수 등을 가져 오지 않고 항상 모듈 만 가져옵니다 .
Alex Martelli

3
반대 투표. 왜? 이것은 정답이 아닙니다. 정답은 Catskul이 '12 년 7 월 30 일 15:04에 나왔습니다.
MEH

105

대답

내 테스트에서 간단한을 제안하는 표시된 답변 reload(X)이 작동하지 않습니다.

내가 정답을 말할 수있는 것은 다음과 같습니다.

from importlib import reload # python 2.7 does not require this
import X
reload( X )
from X import Y

테스트

내 테스트는 다음과 같습니다 (Python 2.6.5 + bpython 0.9.5.2)

X.py :

def Y():
    print "Test 1"

bpython :

>>> from X import Y
>>> print Y()
Test 1
>>> # Edit X.py to say "Test 2"
>>> print Y()
Test 1
>>> reload( X )  # doesn't work because X not imported yet
Traceback (most recent call last):
  File "<input>", line 1, in <module>
NameError: name 'X' is not defined
>>> import X
>>> print Y()
Test 1
>>> print X.Y()
Test 1
>>> reload( X ) # No effect on previous "from" statements
>>> print Y()
Test 1
>>> print X.Y() # first one that indicates refresh
Test 2
>>> from X import Y
>>> print Y()
Test 2 
>>> # Finally get what we were after

1
와. 나는 이것이 정말 편리하다는 것을 알았다. 감사! 지금은 이것을 하나의 라이너로 사용합니다. import X; reload (X); X에서 가져 오기 Y
otterb 2014

1
이것은 받아 들여진 것보다 더 나은 대답입니다. 사람들에게 경고하는 것은 공정하지만 모든 사람의 사용 사례는 다릅니다. 어떤 경우에는 클래스를 다시로드하는 것이 정말 도움이됩니다. 예를 들어 파이썬 콘솔을 사용하고 세션을 잃지 않고 코드에 변경 사항을로드하려는 경우입니다.
nicb

1
이것은 항상 작동하지 않는 것 같습니다. 하위 모듈을 가져 오는 모듈 Foo이 있습니다 __init__.py. 반례로 답변을 게시하겠습니다.
Jason S

이제 Python 3 1 개 라이너 : import importlib; import X; importlib.reload (X); X import Y
Wayne

12
from modulename import func

import importlib, sys
importlib.reload(sys.modules['modulename'])
from modulename import func

이것은 당신이 가져온 방법을 정확하게 기억하지 수 있기 때문에 가장 좋은 방법은 IMO입니다
portforwardpodcast

이것이 원래 질문에 대한 유일한 해결책이며 투표 수가 너무 적습니다!
CharlesB

1
파이썬 3에서 추가 : importlib import reload
mirek

6

우선 재 장전을 피할 수 있다면 전혀 사용하지 말아야합니다. 하지만 이유가 있다고 가정 해 봅시다 (예 : IDLE 내부에서 디버깅).

라이브러리를 다시로드해도 이름이 모듈의 네임 스페이스로 다시 들어오지 않습니다. 이렇게하려면 변수를 다시 할당하면됩니다.

f = open('zoo.py', 'w')
f.write("snakes = ['viper','anaconda']\n")
f.close()

from zoo import snakes
print snakes

f = open('zoo.py', 'w')
f.write("snakes = ['black-adder','boa constrictor']\n")
f.close()

import zoo
reload(zoo)
snakes = zoo.snakes # the variable 'snakes' is now reloaded

print snakes

몇 가지 다른 방법으로이 작업을 수행 할 수 있습니다. 로컬 네임 스페이스를 검색하고 문제의 모듈에서 가져온 모든 것을 다시 할당하여 프로세스를 자동화 할 수 있지만 우리는 충분히 악하다고 생각합니다.


4

이렇게하려면 다음을 수행하십시오.

from mymodule import myobject

대신 다음을 수행하십시오.

import mymodule
myobject=mymodule.myobject

이제 계획했던 것과 같은 방식으로 myobject를 사용할 수 있습니다 (모든 곳에서 귀찮은 읽을 수없는 mymodule 참조없이).

대화식으로 작업 중이고 mymodule에서 myobject를 다시로드하려면 이제 다음을 사용할 수 있습니다.

reload(mymodule)
myobject=mymodule.myobject

2

을 사용했다고 가정하면 from X import Y두 가지 옵션이 있습니다.

reload(sys.modules['X'])
reload(sys.modules[__name__]) # or explicitly name your module

또는

Y=reload(sys.modules['X']).Y

몇 가지 고려 사항 :

A. 가져 오기 범위가 모듈 전체가 아닌 경우 (예 : 함수에서 가져 오기)-두 번째 버전을 사용해야합니다.

B. Y를 다른 모듈 (Z)에서 X로 가져온 경우-X를 다시로드하고 모듈을 다시로드하는 것보다 Z를 다시로드해야합니다. 모든 모듈을 다시로드 (예 : using [ reload(mod) for mod in sys.modules.values() if type(mod) == type(sys) ]) 하더라도 Z를 다시로드하기 전에 X를 다시로드 할 수 있습니다. Y 값을 새로 고치지 마십시오.


1
  1. reload()모듈 X,
  2. reload()가져 오기 모듈 Y에서 X.

다시로드해도 다른 네임 스페이스에 바인딩 된 이미 생성 된 객체는 변경되지 않습니다 (Alex의 스타일 가이드를 따르더라도).


1

경우 당신은 jupyter 환경에서 최선을 다하고, 당신은 이미 from module import function, 마법 기능을 사용할 수 있습니다 autoreload에 의해

%load_ext autoreload
%autoreload
from module import function

autoreloadin IPython 의 소개는 여기에 있습니다 .


0

AlexMartelliCatskul의 답변에 대한 후속 조치를 취하기 위해 reload적어도 Python 2에서는 혼란스러워 보이는 매우 간단하지만 불쾌한 사례가 있습니다.

다음 소스 트리가 있다고 가정합니다.

- foo
  - __init__.py
  - bar.py

다음 내용으로 :

init.py :

from bar import Bar, Quux

bar.py :

print "Loading bar"

class Bar(object):
  @property
  def x(self):
     return 42

class Quux(Bar):
  object_count = 0
  def __init__(self):
     self.count = self.object_count
     self.__class__.object_count += 1
  @property
  def x(self):
     return super(Quux,self).x + 1
  def __repr__(self):
     return 'Quux[%d, x=%d]' % (self.count, self.x)

다음을 사용하지 않고도 잘 작동합니다 reload.

>>> from foo import Quux
Loading bar
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> Quux()
Quux[2, x=43]

그러나 재 장전을 시도하면 효과가 없거나 손상됩니다.

>>> import foo
Loading bar
>>> from foo import Quux
>>> Quux()
Quux[0, x=43]
>>> Quux()
Quux[1, x=43]
>>> reload(foo)
<module 'foo' from 'foo\__init__.pyc'>
>>> Quux()
Quux[2, x=43]
>>> from foo import Quux
>>> Quux()
Quux[3, x=43]
>>> reload(foo.bar)
Loading bar
<module 'foo.bar' from 'foo\bar.pyc'>
>>> Quux()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo\bar.py", line 17, in __repr__
    return 'Quux[%d, x=%d]' % (self.count, self.x)
  File "foo\bar.py", line 15, in x
    return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> Quux().count
5
>>> Quux().count
6
>>> Quux = foo.bar.Quux
>>> Quux()
Quux[0, x=43]
>>> foo.Quux()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "foo\bar.py", line 17, in __repr__
    return 'Quux[%d, x=%d]' % (self.count, self.x)
  File "foo\bar.py", line 15, in x
    return super(Quux,self).x + 1
TypeError: super(type, obj): obj must be an instance or subtype of type
>>> foo.Quux().count
8

bar하위 모듈이 다시로드 되었는지 확인할 수있는 유일한 방법 은 다음과 같습니다 reload(foo.bar). 다시로드 된 Quux클래스에 액세스하는 유일한 방법 은 다시로드 된 하위 모듈에 접근하여 가져 오는 것입니다. 하지만, foo모듈 자체는 원래 붙잡고 유지 Quux가 아마 사용하기 때문에, 클래스 오브젝트 from bar import Bar, Quux(보다는 import bar하였다 Quux = bar.Quux); 더군다나 Quux학급은 그 자체로 동기화되지 않았는데, 이는 기괴합니다.

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