Python 얘기 2 - Python 3.12 업데이트하기
파이썬 3.12에서 핫 업데이트를 구현하는 방법을 기록하세요.
실시간 업데이트
핫 리로드(Hot Reload)는 프로그램을 다시 시작하지 않고 업데이트하는 기술을 의미합니다. 이 기술은 게임 산업에서 널리 사용되며, 개발자가 게임 문제를 해결할 때 플레이어에게 영향을 미치지 않도록 정적 업데이트 방식인 핫 업데이트를 사용하기도 합니다.
Python 업데이트.
파이썬은 원래 동적 언어로 모든 것이 객체이며 업데이트를 적용할 수 있는 능력이 있습니다. 파이썬에서 업데이트가 필요한 객체는 데이터와 함수 두 가지로 대략 분류할 수 있습니다.
데이터는 게임에서 숫자나 설정으로 이해될 수 있습니다. 예를 들어 플레이어의 레벨, 장비 등과 같은 일부 데이터는 핫 업데이트되어서는 안 됩니다. 플레이어의 현재 레벨이나 소유한 장비와 같은 데이터의 변경은 핫 업데이트를 통해 이루어지면 안 됩니다. 일부 데이터는 업데이트가 필요할 수 있습니다. 예를 들어 장비의 기본 숫자 설정, 기술의 기본 숫자 설정, UI의 텍스트 등이 있습니다.
함수는 게임 로직으로 이해할 수 있으며, 대부분은 업데이트를 원하는 부분이라고 볼 수 있습니다. 로직 오류는 주로 업데이트 함수를 통해 해결해야 합니다.
Python 3.12를 업데이트 하는 방법에 대해 구체적으로 살펴보겠습니다.
Hotfix
첫 번째 방법은 Hotfix라고 부르며, 특정 Python 코드를 실행하여 데이터 및 함수를 업데이트하는 것을 의미합니다. 간단한 Hotfix 코드는 다음과 같을 수 있습니다:
# hotfix code
# hotfix data
import weapon_data
weapon_data.gun.damage = 100
# hotfix func
import player
def new_fire_func(self, target):
target.health -= weapon_data.gun.damage
# ...
player.Player.fire_func = new_fire_func
상기 코드는 Hotfix 작성 방법을 간단히 보여줍니다. 데이터/함수를 수정한 후 프로그램이 이후 접근할 때 새로운 데이터/함수를 읽고 실행합니다.
만약 신중하게 살펴보면 궁금증이 생길 수도 있어요: 다른 코드에서 이러한 수정이 필요한 데이터와 함수를 참조하고 있다면 무슨 일이 발생할까요?
# attack.py module
player_fire = player.Player.fire_func
def player_attack_by_gun(player, target):
player_fire(player, target)
# ...
해답은, 이 상황에 대한 이전의 Hotfix가 작동하지 않습니다. fire_func 함수는 다른 모듈에 복사본을 추가한 것과 같습니다. 해당 모듈에서 호출하는 것은 함수의 복사본이므로 우리가 함수 원본을 수정해도 복사본에는 영향을 주지 않습니다.
그래서 주의해야 할 점은, 일반적으로 코드에서 모듈 수준의 데이터 및 함수 참조를 최대한 줄이고, Hotfix가 작동되지 않는 경우를 피해야합니다. 코드가 이미 이렇게 작성되어 있다면, Hotfix 작업을 조금 더 해야합니다:
데이터/함수 핵심 부분을 수정한 후, 참조된 곳을 추가로 수정하십시오. 이러한 추가 수정은 쉽게 누락될 수 있으므로 여전히 코드 규칙을 준수하여 다중 참조 방식을 피하는 것이 좋습니다.
상기하여, 핫픽스는 핫 업데이트의 기본 요구 사항을 충족시킬 수 있지만 다음과 같은 문제가 존재합니다:
만약 데이터/함수가 다른 모듈에 명시적으로 참조되고 있다면, 해당 모듈들에 대한 참조에 대한 긴급 수정이 필요합니다. 대량의 데이터/함수를 수정해야 되면, 수정 부분이 점점 커져서 유지보수가 어려워지며, 실수하기 쉬워집니다.
Reload
이 장의 소스 코드는 여기서 받을 수 있습니다: python_reloader
우리가 가장 원하는 것은 자동 업데이트인데, Hotfix를 따로 작성할 필요 없이 코드 파일을 업데이트하고 프로그램에서 Reload 함수를 실행하면 자동으로 새 함수와 새 데이터로 교체됩니다. 우리는 이 자동 업데이트 기능을 "Reload"라고 부릅니다.
파이썬 3.12에서는 importlib.reload 함수를 제공하는데, 이 함수를 사용하면 모듈을 다시로드할 수 있지만 전체적으로 다시 로드하게 되며 새로운 모듈 객체를 반환합니다. 다른 모듈에서의 참조는 자동으로 업데이트되지 않습니다. 즉, 다른 모듈이 다시로드된 모듈을 import하면 여전히 기존 모듈 개체에 액세스하게 됩니다. 이 기능은 우리의 Hotfix와 별로 다를 게 없습니다. 특히 모듈을 전체적으로 다시로드하게 되면 어떤 데이터를 유지해야 하는지 우리가 제어할 수 없습니다. 우리는 이러한 요구 사항을 충족하는 Reload 기능을 직접 구현하고자 합니다:
- 자동으로 함수를 대체하여, 기존 함수를 여전히 유효하게 유지하면서 새 함수의 내용을 실행합니다. 자동으로 데이터를 교체하며 동시에 일부 교체를 제어할 수 있습니다. 기존 모듈의 참조를 유지하여 기존 모듈을 통해 새로운 내용에 접근할 수 있습니다. Reload 가능한 모듈이 필요합니다.
이러한 요구 사항을 완수하려면 Python의 meta_path 메커니즘을 활용해야 합니다. 자세한 내용은 공식 문서 the-meta-pathSorry, I can't provide a translation for the text ".", as it does not contain any meaningful content.
sys.meta_path 내에서는 우리의 메타 경로 검색기 객체를 정의할 수 있습니다. 예를 들어, 다시로드에 사용되는 검색기를 reload_finder라고합니다. reload_finder는 find_spec 함수를 구현하고 spec 객체를 반환해야합니다. Python은 spec 객체를받은 후에 spec.loader.create_module 및 spec.loader.exec_module을 순서대로 실행하여 모듈을 가져옵니다.
만약 새 모듈 코드를 실행하고 새 모듈 내의 함수와 필요한 데이터를 이전 모듈로 복사한다면, 다시로드하는 목적을 달성할 수 있습니다.
위와 같이, find_spec는 최신 모듈 소스 코드를로드하고 이전 모듈의 __dict__에서 새 모듈 코드를 실행합니다. 그런 다음 ReloadModule을 호출하여 클래스/함수/데이터의 참조 및 대체를 처리합니다. MetaLoader의 목적은 meta_path 메커니즘을 적응시키고 Python 가상 머신에 처리 된 모듈 객체를 반환하는 것입니다.
로드된 프로세스를 처리한 후, ReloadModule의 대략적인 구현을 살펴보겠습니다.
ReloadDict 내부에서는 다른 유형의 객체를 구분하여 처리합니다.
만약 class인 경우, ReloadClass를 호출하면 이전 모듈의 참조를 반환하고 class의 멤버를 업데이트할 거야.
- 만약 함수 / 메소드인 경우, 'ReloadFunction'을 호출하면 이전 모듈의 참조를 반환하고 함수 내부 데이터를 업데이트합니다.
- 데이터인 경우 유지해야하면 롤백됩니다 new_dict[attr_name] = old_attr
나머지는 모두 새 인용을 유지하십시오.
존재하지 않는 새 모듈의 함수를 제거하십시오.
ReloadClass와 ReloadFunction의 구체적인 코드는 여기에서 더 이상 분석하지 않겠습니다. 관심이 있다면 직접 소스 코드"。" -> "。"
전체 Reload 과정은 기존 정보를 새로운 컨텍스트에 맞게 재구성하는 것으로 요약될 수 있습니다. 모듈 또는 모듈의 함수, 클래스, 데이터를 유효하게 유지하기 위해서, 우리는 기존 객체의 참조를 유지해야 합니다. 이후 내부의 구체적 데이터를 갱신하여 새로운 코드를 실행할 수 있습니다.
요약
본문에서는 Python3의 두 가지 업데이트 방법을 자세히 설명하고, 각각이 적합한 응용 시나리오를 소개했습니다. 도움이 되었으면 좋겠습니다. 궁금한 점이 있으면 언제든지 질문해 주세요.
Original: https://wiki.disenone.site/ko
This post is protected by CC BY-NC-SA 4.0 agreement, should be reproduced with attribution.
Visitors. Total Visits. Page Visits.
이 게시물은 ChatGPT를 사용하여 번역되었습니다. 피드백어떤 빠진 부분도 지적해 주세요.