Python 개체를 올바르게 정리하려면 어떻게 해야 합니까?
class Package:
def __init__(self):
self.files = []
# ...
def __del__(self):
for file in self.files:
os.unlink(file)
__del__(self)
AttributError 예외로 인해 장애가 발생합니다.Python은 다음과 같은 경우에 "글로벌 변수"(이 컨텍스트의 멤버 데이터)의 존재를 보증하지 않는 것으로 알고 있습니다.__del__()
이런 어떻게 수 요?이것이 예외의 이유일 경우 오브젝트가 올바르게 파괴되도록 하려면 어떻게 해야 합니까?
Python을 하는 것을 with
정리해야 하는 리소스를 관리하기 위한 문입니다. 사용 close()
이 있는 것을 .finally
예외 발생 시 리소스 누출을 방지하기 위해 block을 클릭합니다.
「 」를 with
statement adda, adda의 .
def __enter__(self)
def __exit__(self, exc_type, exc_value, traceback)
위의 예에서는 다음을 사용합니다.
class Package:
def __init__(self):
self.files = []
def __enter__(self):
return self
# ...
def __exit__(self, exc_type, exc_value, traceback):
for file in self.files:
os.unlink(file)
그런 다음 다른 사람이 당신의 수업을 사용하려고 하면 다음과 같이 합니다.
with Package() as package_obj:
# use package_obj
유형의 인스턴스가 (Package_obj "Package"에 입니다).__enter__
메서드).그것의.__exit__
예외 발생 여부에 관계없이 메서드가 자동으로 호출됩니다.
한 걸음 더 나아갈 수도 있습니다.할 수 .이러한 예에서는 생성자를 하지 않아도 .with
절을 클릭합니다.★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★ PackageResource 클래스를 .__enter__
★★★★★★★★★★★★★★★★★」__exit__
클래스는 말하면 패키지 클래스가 됩니다.__enter__
메서드를 반환했습니다.는 「」를 할 수 .with
★★★★★★★★
class PackageResource:
def __enter__(self):
class Package:
...
self.package_obj = Package()
return self.package_obj
def __exit__(self, exc_type, exc_value, traceback):
self.package_obj.cleanup()
다음과 같이 사용할 수 있습니다.
with PackageResource() as package_obj:
# use package_obj
표준적인 방법은 다음과 같습니다.
# package.py
import atexit
import os
class Package:
def __init__(self):
self.files = []
atexit.register(self.cleanup)
def cleanup(self):
print("Running cleanup...")
for file in self.files:
print("Unlinking file: {}".format(file))
# os.unlink(file)
, 이 생성된 는 그대로 해야 합니다.Package
Python 。
패키지로 저장된 위의 코드를 사용하여 데모합니다.py:
$ python
>>> from package import *
>>> p = Package()
>>> q = Package()
>>> q.files = ['a', 'b', 'c']
>>> quit()
Running cleanup...
Unlinking file: a
Unlinking file: b
Unlinking file: c
Running cleanup...
Clint의 답변에 대한 부록으로서PackageResource
사용:
@contextlib.contextmanager
def packageResource():
class Package:
...
package = Package()
yield package
package.cleanup()
수도 , ,, 처, 토, 선, 선, 선, 선, 선, 선, 선, 선, 선을 덮어쓸 .Package.__new__
:
class Package(object):
def __new__(cls, *args, **kwargs):
@contextlib.contextmanager
def packageResource():
# adapt arguments if superclass takes some!
package = super(Package, cls).__new__(cls)
package.__init__(*args, **kwargs)
yield package
package.cleanup()
def __init__(self, *args, **kwargs):
...
사용하시면 됩니다.with Package(...) as package
.
을 짧게 기능의 을 대세요.close
및 use를 사용합니다.이 경우 수정되지 않은 명령어를 사용할 수 있습니다.Package
통한 with contextlib.closing(Package(...))
그 「」를 .__new__
말하면
class Package(object):
def __new__(cls, *args, **kwargs):
package = super(Package, cls).__new__(cls)
package.__init__(*args, **kwargs)
return contextlib.closing(package)
그리고 이 생성자는 상속되므로 간단히 상속할 수 있습니다.
class SubPackage(Package):
def close(self):
pass
더 나은 대안은 weakref를 사용하는 것입니다.마무리짓다Finalizer Objects 및 __del_() 메서드를 사용한 파이널라이저 비교 예제를 참조하십시오.
before스턴 to i i i 、 to to 、 인 members 、 i i 、 i i 、 i i 、 i i 、 i i 、 i i 、 i i 、 i i i 。__del__
은 다른해서 자신을삭제했을 수도 ).특정 AttributeError의 원인은 다른 곳에 있을 것으로 추측됩니다(실수로 자신을 삭제했을 가능성이 있습니다).하다
다른 처럼 ,, 른, 른, 다, 다, 다, 다, 다, 다, 다, 니, 니, 니, however, however, however, however, however, however, however, however, however, however, however, however, however, however ,__del__
는 . 하다, 하다, 하다, 하다, 이런 경우가 있기 __del__
가비지가 수집되지 않습니다(refcount가 0에 도달한 경우에만 해방됩니다).따라서 인스턴스가 순환 참조에 관련되어 있는 경우 응용 프로그램이 실행되는 한 해당 인스턴스는 메모리에 계속 남아 있습니다(단, gc 문서를 다시 읽어야 하지만 이렇게 동작할 수 있다고 확신합니다).
다음은 최소한의 동작 스켈레톤입니다.
class SkeletonFixture:
def __init__(self):
pass
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
pass
def method(self):
pass
with SkeletonFixture() as fixture:
fixture.method()
중요: 리턴 셀프
이고, 주는 사람이고, 눈감아 주는 이고, 눈감아 주는 사람이고, 눈감아 주는 사람이고, 눈감아 주는 사람이고, 눈감아 주는 사람이고, 눈감아 주는 사람이고, 눈감아 주는 사람이고.return self
(클린트 밀러의 정답 중) 당신은 이 말도 안 되는 것을 보게 될 것이다.
Traceback (most recent call last):
File "tests/simplestpossible.py", line 17, in <module>
fixture.method()
AttributeError: 'NoneType' object has no attribute 'method'
다음 사람에게 도움이 되길 바랍니다.
가 될 수 합니다.__init__
표시된 것보다 더 많은 코드가 있는 경우
__del__
__init__
제대로 실행되지 않았거나 예외가 발생했습니다.
destructor를 try/except 문장으로 감싸기만 하면 글로벌이 이미 폐기된 경우 예외가 발생하지 않습니다.
편집
이것을 시험해 보세요.
from weakref import proxy
class MyList(list): pass
class Package:
def __init__(self):
self.__del__.im_func.files = MyList([1,2,3,4])
self.files = proxy(self.__del__.im_func.files)
def __del__(self):
print self.__del__.im_func.files
콜 시에 존재하는 것이 보증되는 del 함수에 파일목록을 채웁니다.weakref 프록시는 Python 또는 자신의 셀프 삭제를 방지하는 것입니다.files variable (삭제해도 원래 파일 목록에는 영향을 주지 않습니다)변수에 대한 참조가 많아도 삭제되지 않으면 프록시 캡슐화를 삭제할 수 있습니다.
이 작업을 수행하는 관용적인 방법은 다음과 같은 정보를 제공하는 것 같습니다.close()
방법(또는 유사)을 설명으로 부릅니다.
atexit.register
오스트라카흐의 답변에 이미 언급된 표준적인 방법입니다.
단, 아래 예시와 같이 오브젝트가 삭제될 가능성이 있는 순서는 신뢰할 수 없습니다.
import atexit
class A(object):
def __init__(self, val):
self.val = val
atexit.register(self.hello)
def hello(self):
print(self.val)
def hello2():
a = A(10)
hello2()
a = A(20)
여기서 순서는 프로그램으로 오브젝트가 생성된 순서의 역순으로 다음과 같이 출력됩니다.
20
10
그러나 더 큰 프로그램에서 파이썬의 수명이 다한 오브젝트를 발로 차게 되면 파이썬의 가비지 컬렉션이 먼저 파괴됩니다.
가장 좋은 방법은 두 가지 방법을 결합하는 것입니다.
명시적인 라이프 사이클 처리를 위한 컨텍스트 매니저를 구현합니다.또한 사용자가 이를 잊어버렸거나 문과 함께 사용하는 것이 편리하지 않은 경우에 대비한 청소도 수행합니다.이것은 weakref에 의해 가장 잘 수행된다.마무리짓다
많은 도서관들이 실제로 이렇게 하고 있습니다.또한 심각도에 따라 경고를 보낼 수도 있습니다.
import os
from typing import List
import weakref
class Package:
def __init__(self):
self.files = []
self._finalizer = weakref.finalize(self, self._cleanup_files, self.files)
@staticmethod
def _cleanup_files(files: List):
for file in files:
os.unlink(file)
def __enter__(self):
return self
def __exit__(self, exc_type, exc_value, traceback):
self._finalizer()
"weakref.finalize는 obj가 가비지 수집되었을 때 호출되는 호출 가능한 피니셔 객체를 반환합니다.일반적인 약한 레퍼런스와는 달리 피니셔는 레퍼런스 오브젝트가 수집될 때까지 항상 존속하기 때문에 라이프 사이클 관리가 대폭 간소화됩니다."
atexit.register와는 달리 오브젝트는 인터프리터가 셧다운될 때까지 메모리에 유지되지 않습니다.
그리고 물건과는 다르게.__del__,weakref.finalize
인터프리터 셧다운 시 콜이 보증됩니다.그래서 훨씬 더 안전하다.
언급URL : https://stackoverflow.com/questions/865115/how-do-i-correctly-clean-up-a-python-object
'programing' 카테고리의 다른 글
Netty vs Apache MINA (0) | 2022.10.18 |
---|---|
MySQL DEFAULT vsMariaDB 디폴트 (0) | 2022.10.18 |
MariaDB는 MYSQL/Oracle JSON_TAB의 스케일러블 등가값을 가지고 있습니까?LE (0) | 2022.10.08 |
Nuxt.js에서의 CORS 차단 클라이언트 요구 (0) | 2022.10.08 |
Chrome에서 동일한 원본 정책 사용 안 함 (0) | 2022.10.08 |