소개

파이썬 3 버전으로의 마지막 주요 업그레이드는 거의 12년 전인 2008년 12월에 이루어졌습니다. 하지만 아직 Python 2 제품이나 테스트 코드를 사용하고 계실 가능성이 높습니다. 그렇다면 사용 중인 Python 버전을 업데이트하라는 알림으로 아래 사용 중단 메시지가 표시될 수 있습니다.

"알림: Python 2.7은 2020년 1월 1일에 수명이 종료됩니다. 이 날짜 이후에는 파이썬 2.7이 유지 관리되지 않으므로 파이썬을 업그레이드하세요. 향후 버전의 pip에서는 Python 2.7에 대한 지원이 중단됩니다."

이를 심각하게 받아들이고 그에 따라 계획을 세우시기 바랍니다: Python 3.x 업데이트는 이전 버전과 호환되지 않습니다. Python 2.x 버전으로 작성한 내용이 3.x를 사용할 때 제대로 작동하지 않을 수 있습니다..

작은 글씨도 꼭 읽어보세요. 프로그래밍 언어 웹사이트에 따르면 파이썬의 최종 업그레이드 릴리스 날짜는 아직 미정입니다. "2.x 시리즈의 마지막 버전인 2.7은 2020년까지 버그 수정 지원을 받을 수 있습니다. 공식적으로 2020년 1월 1일에 지원이 중단되지만 최종 릴리즈는 그 이후에 이루어질 예정입니다." [1]

따라서 Python 2는 올해 말까지 지원되지 않는 모드로 전환됩니다. 아직 마이그레이션하지 않으셨다면 지금이 현재 Python 2 코드를 Python 3 구문으로 마이그레이션하고 앞으로는 Python 3을 고수하기에 좋은 시기입니다.

팀에서 바로 Python 2에서 3으로의 마이그레이션을 시작하지 않는 이유는 무엇일까요? 가장 큰 장애물 중 하나는 대부분의 작업 코드가 단순히 깨진다는 것입니다( 왜 파이썬 3이 파이썬 2와 호환되지 않는가?), 직접 언어 구문이나 타사 API의 문제로 인해 마이그레이션이 필요한 경우가 있습니다. 공정하게 말하자면, 새로운 Python 업데이트가 이전 버전과 호환된다면 마이그레이션에 신경 쓸 사람은 거의 없을 것입니다. 대신 버전 2가 지원되지 않기 때문에 Couchbase를 포함한 많은 사람들이 마이그레이션을 우선시하게 될 것입니다. 팀이 버그 수정 지원 기한을 넘기더라도 코드는 계속 작동하므로 괜찮습니다. 팀으로서 우리는 가능한 한 이 날짜에 가깝게 마이그레이션하여 다른 Python 커뮤니티 구성원들과 같은 정보를 공유하고 함께 배우는 것이 더 낫다고 결정했습니다.  

이 문서는 Python 3으로 업그레이드하는 동안 배운 팁과 요령, 그리고 Couchbase 테스트 인프라 마이그레이션 과정에서 겪은 일반적인 문제를 정리한 것입니다. 보시다시피 저희는 자동화된 프로세스로 킥스타트한 후 명령줄을 통해 수동으로 Python을 업데이트합니다. 여러분의 접근 방식은 다를 수 있습니다. 어쨌든 가능한 한 빨리 시작하세요. 파이썬을 버전 2에서 버전 3으로 업데이트하는 것이 중요합니다.

카우치베이스 는 오픈 소스 엔터프라이즈급 멀티클라우드-에지 NoSQL 데이터베이스입니다. Couchbase 기능 테스트 프레임워크인 TestRunner는 Python 2로 개발되었습니다. TestRunner git 리포지토리는 다음에서 찾을 수 있습니다. https://github.com/couchbase/testrunner . 이제 우리의 목표는 파이썬 3과 파이썬 2를 함께 실행하는 대신 파이썬 3 런타임으로 완전히 전환하는 것입니다.

Python 업그레이드 프로세스의 일환으로 버전 3으로 성공적으로 포팅하는 데 필요한 주요 변경 사항을 확인했습니다. 이 글에서는 포팅 과정에서 확인된 몇 가지 문제에 대해 설명합니다. 저희의 학습 내용을 공유하는 목적은 여러분의 마이그레이션에 도움이 되고자 하는 것입니다. 최신 Python 3.x 버전(특정 플랫폼의 안정적이고 보안이 수정된 사전 릴리스 버전인 3.7 또는 3.6에 따라 다름)을 선택할 수 있으며, 이 블로그 전체에서 Python 3이라고 부릅니다. 릴리스에 대한 자세한 내용은 다음에서 확인하세요. Python 릴리스 다운로드 그리고  Python 3 문서.

치트 시트

 

주요 변경 사항: 파이썬 2와 파이썬 3

파이썬 2와 파이썬 3의 주요 차이점을 파악하기 위해 필요한 코드 변경 사항의 요약 목록은 다음과 같습니다.

Python 2 Python 3
텍스트 utf-8 : str
텍스트는 유니코드 : str
u"
바이너리는 텍스트와 동일합니다: 바이트/스트링
예시:
file.read(6) == 'GIF89a'
바이너리 데이터는 b 접두사: 바이트로 표시됩니다.
 b"
문자열을 가져오려면 decode(), 바이트를 가져오려면 encode()를 사용합니다.예시: 
file.read(6) == b'GIF89a'
b'hello'.decode() → 'hello'
'hello'.encode() → b'hello'
str(b'hello') → "b'hello'
명세서 인쇄
예: 인쇄 ' '
인쇄 기능
예:인쇄(' ')
정수 나누기
예시: 5/2=2
바닥 분할. 슬래시 2개 사용
예시: 예: 5//2 = 2 및 5/2 = 2.5
부동 소수점 나누기
예시: 5/2.0 = 2.5 또는 5.0/2 = 2.5
플로트 분할. 단일 슬래시 사용
예시: 5/2 = 2.5
긴 유형은 int와 다릅니다.
long 
긴 유형은 없습니다. int와 동일합니다.
xrange() 범위()
반복 함수에는 iter 접두사가 있습니다. iterxxx()
예: iteritems()
삭제된 이터 접두사. xxxx()
예: items()
목록이 직접 로드됩니다(목록 사용 시 모든 요소가 메모리에 로드됨).
예: []에서 i의 경우 
목록은 지연 로드됩니다(요소에 액세스할 때 메모리에만 로드됨).
예: 목록([])에서 i의 경우 
사전은 기본적으로 또는 2개의 사전과 비교할 수 있습니다.
예: sorted(dict) 
정렬()에는 키가 있어야 합니다.

예시: sorted(expected_result,key=(lambda x: x[bucket.name]['name']))일반적인 딕셔너리/목록 비교는 아래를 참조하세요: 
 딥디프에서 딥디프 가져오기
 diffs = DeepDiff(actual_result['results'], expected_result['results'], 무시_순서=True)만약 차이점:
   self.assertTrue(False, diffs)

바이트 및 문자열을 값으로 사용합니다:
diffs = DeepDiff(set(실제_인덱스), set(인덱스_이름), 무시_순서=True, 무시_스트링 유형 변경 무시=True)

string.replace(data[i],...) data[i].replace(..)
urllib.urlencode() 새로운 모듈

  • http.client
  • urllib.요청, urllib.오류, urllib.파싱
  • sgmllib3k

예시: 
urllib.parse.urlencode()

문자열.소문자 속성:
string.ascii_소문자
string.ascii_대문자

참조 testrunner py3 커밋  변경 사항

Python 3 설정

Python 3을 처음부터 설정하려면 주요 지원 플랫폼이 있는 새 호스트에서 아래 명령을 실행하세요.
나중에 런타임 중에 파이썬 3 명령어 또는 파이썬 3 가상 환경의 파이썬을 사용합니다. 설치된 파이썬 3 버전을 기반으로 패키지를 설치하려면 pip3 또는 pip3.x(예: pip3.6)를 사용합니다.

Mac OS
(예: 노트북)
직접 설정(pip3가 자동으로 설치됨):(https://wsvincent.com/install-python3-mac/)

가상 환경 설정:

필요한 라이브러리를 설치합니다:

현재로서는 일반적인 Python 3 http 클라이언트에 아래 수정이 필요하며, 그렇지 않으면 오류가 발생합니다.

 
CentOS  
(예제 노드: 젠킨스 슬레이브)
직접 설정 및 가상 환경:

필요한 라이브러리를 설치합니다:

 

새 슬레이브에 Couchbase CSDK 및 Python SDK 설치를 수행합니다:

현재로서는 일반적인 Python 3 http 클라이언트에 아래 수정이 필요하며, 그렇지 않으면 오류가 발생합니다.

 

Python 3 런타임 검증에 사용하는 Ubuntu 슬레이브
직접 설정:

 

필요한 라이브러리를 설치합니다:

CSDK 및 Python SDK 설치: (참고: https://docs.couchbase.com/c-sdk/2.10/start-using-sdk.html )

현재로서는 일반적인 Python 3 http 클라이언트에 아래 수정이 필요하며, 그렇지 않으면 오류가 발생합니다.

 

Windows
다운로드하여 설치합니다: https://www.python.org/ftp/python/3.7.4/python-3.7.4.exe

필요한 라이브러리를 설치합니다:

 

포팅 프로세스

포팅은 크게 3단계로 진행됩니다. 1) 자동 변환 2) 수동 변경 3) 런타임 유효성 검사 및 수정

처음에는 원본 리포지토리를 복제하고 기본 자동 변환 변경 사항을 적용합니다. 전체 변환이 완료될 때까지 변경 사항을 새 리포지토리로 체크인하세요. 이렇게 하면 현재 회귀 주기를 중단 없이 진행할 수 있습니다.

1. 자동 변환

라는 자동화된 도구가 있습니다. 2to3 도구는 인쇄, 예외, 목록 래핑, 상대 임포트 등과 같은 몇 가지 일반적인 패턴을 처리하는 데 도움이 되는 파이썬 3 팀에서 제공하는 함수입니다.  

로컬로 복제된 작업 공간에서 단일 디렉토리로 시작하여 다시 확인할 수 있습니다. 나중에 전체 코드에 대해 변환을 수행하여 기본적인 포팅을 처리할 수 있습니다.

다음은 MacOS에서 2대 3으로 변환하는 몇 가지 샘플 명령어입니다. 마지막 명령에서는 모든 관용구가 적용되었다는 점에 유의하세요. 이렇게 하면 처음 변환할 때 주요 변경 사항을 처리할 수 있습니다.

 

2. 수동 변경

자동 변환은 완전한 포팅을 수행하지 않습니다. 자동 변환 2to3 도구가 수행하는 일반적인 구문 변경보다 포팅 프로세스 중에 다음과 같은 일반적인 문제가 발생할 수 있습니다. 

테스트 클래스를 실행하여 오류가 있는지 확인하고 적절하게 수정하여 바이트에서 문자열로 또는 문자열에서 바이트로 전환할지 또는 정렬된 함수의 키 이름을 수정해야 하는 정렬/비교 문제를 해결할지 결정합니다. 이 과정은 모든 코드 런타임의 유효성이 검사될 때까지 반복적으로 수행됩니다.

공통 패턴이 확실해지면 grep과 sed를 사용하여 여러 클래스 파일에서 바꿀 수 있습니다. 런타임까지 다른 코드에 대해 확실하지 않은 경우 해당 테스트 클래스가 실행될 때까지 연기하세요. 

타사 라이브러리/모듈에 문제가 있거나 변경되었을 수 있으므로 웹에서 검색하여 적절하게 사용해야 합니다.

지원되는 모든 플랫폼과 매개변수에서 실행하여 모든 코드 경로가 포함되는지 확인하세요.

3. 런타임 검증 및 수정

변환이 완료되면 파이썬은 동적 언어이므로 많은 코드 런타임을 수행하세요. 그렇지 않고 시각적으로 정적 코드 검사/변경만 수행하면 변경 사항으로 인해 문제가 발생할 수 있습니다. 기본 정상 테스트, 수락 테스트부터 시작한 다음 단일 테스트 모듈에서 전체 테스트를 선택할 수 있습니다.

익숙해지면 다른 모든 모듈을 하나씩 적용하세요. 새 리포지토리에 변경 사항을 계속 체크인하세요. 또한 최신 빌드에서 정상 테스트를 실행하여 이 새 리포지토리에서 포팅된 변경 사항에 회귀가 없는지 확인해야 합니다. 또한 유효성 검사에는 Python 3에서 지원되는 모든 플랫폼이 포함되어야 합니다.

 

파이썬 3 포팅된 코드 및 상태

아래는 파이썬 3 포팅된 코드가 메인 리포지토리에 병합될 때까지 새 리포지토리를 찾을 수 있는 곳입니다. 계획은 한 주기의 포팅을 수행하거나 중간에 메인 리포지토리에서 변경 사항을 가져와 이곳으로 수동 병합하는 것입니다.

https://github.com/couchbaselabs/testrunner-py3/

(브랜치: 마스터)

다른 런타임 문제가 있을 수 있으므로 많은 일반적인 변경 사항이 이미 수행되었지만 완료되지 않았습니다. 또한 입력 값 유형 변환에 대한 가정으로 인해 공통 수정 사항이 이전 수정 사항으로 되돌아갈 수도 있습니다. 아직 파이썬 3에서 검증해야 할 포팅된 코드가 더 있으며 이 작업은 계속 진행 중입니다.

이제 일반적인 문제를 보여드리겠습니다. 발생한 런타임 유효성 검사 중입니다. 문제가 발생했을 때 이를 참조하여 비슷한 문제가 발생하는지 확인할 수 있습니다. 동일한 해결 방법을 적용하여 효과가 있는지 확인할 수 있습니다. 그리고 새로운 아이디어가 있다면 댓글에 적어주세요.

일반적인 런타임 문제

 

1. 문제(들):

  • 런타임 중에 바이트 대신 문자열, 문자열 대신 바이트와 같은 아래 TypeError 중 일부가 발생할 수 있습니다.
  • 오류#1. 유형 오류: 문자열을 바이트열로 연결할 수 없습니다.
  • Error#2. TypeError: 바이트가 아닌 문자열이어야 합니다.
  • 오류#3. TypeError: 'str'이 아닌 바이트열과 유사한 객체가 필요합니다.
  • Error#4. TypeError: str과 비-str 인수를 혼합할 수 없습니다.

솔루션:

문에 있는 변수의 유형을 확인하고 xxx.encode()를 사용하여 바이트열을 가져오거나 xxx.decode()를 사용하여 문자열을 가져오거나 접두사 b를 사용하거나 str()을 사용하세요. 때로는 입력을 알 수 없는 경우가 있으며, 이 경우 AttributeError: pass를 제외하고 x.encode()를 사용하세요.


2. 문제(들):

TypeError: root - 오류 - --->설치 실패: 'str'이 아닌 바이트열과 같은 객체가 필요합니다.

솔루션: 

이 경우 비교 대상 문자열에 접두사로 b를 추가하거나 바이트 유형을 문자열 유형으로 변경합니다. 예: lib/remote/remote_util.py

오류를 일으키는 정확한 줄을 확인하는 것을 제외하고는 시도-로 둘러쌉니다(예: 위의 TypeError). 

traceback.print_exec() 뒤의 샘플 출력을 통해 자바처럼 전체 스택 추적을 확인할 수 있습니다.

아래와 같이 lib/remote/remote_util.py를 변경하여 수정합니다.

3. 문제(들):

 

솔루션:

 

4. 문제(들):

일부 테스트 스위트에 대해 suite_setUp() 또는 suite_tearDown()이 누락되었습니다.

솔루션:

더미 suite_setUp() 및 suite_tearDown() 메서드를 추가합니다. 

 

5. 문제(들):

 

솔루션:

 

6. 문제(들):

속성 오류: '전송' 개체에 '_Thread__stop' 속성이 없습니다.

솔루션:

데몬이 아닌 스레드를 직접 중지할 수는 없습니다. 하지만 구문상으로는 t._stop()을 사용합니다. 전역 플래그를 사용하여 정상적으로 종료하고 스레드의 run()을 확인하여 중단하는 것이 좋습니다.

(https://stackoverflow.com/questions/27102881/python-threading-self-stop-event-object-is-not-callable)

7. 문제(들):

테스트 expirytests.ExpiryTests.test_expired_keys를 찾을 수 없습니다: 모듈 '문자열'에 '번역' 속성이 없습니다.

솔루션:

정적 메서드를 사용하여 다시 작성합니다. 모든 문자를 가져오는 이전 방법은 없으므로 이전 코드를 사용하여 총 집합을 사용했습니다.

vi lib/membase/api/tap.py 

 

8. 문제(들):

TabError: 들여쓰기에 탭과 공백이 일관성 없이 사용됨

 

솔루션:

탭 문자를 검색하고 공백 문자로 바꿉니다. 

위 문제의 경우 탭 문자를 제거합니다.

 

9. 문제(들):

솔루션:

대소문자 구분 문제. x_couchbase_meta 키에서 X_Couchbase_Meta로 변경하여 수정되었습니다.

 

10. 문제(들):

  • Error#1. TypeError: 'dict'와 'dict'의 인스턴스 간에는 '<'가 지원되지 않습니다.
  • Error#2. TypeError: 이 함수에 대한 잘못된 키워드 인수가 'cmp'입니다.

솔루션:

   

11. 문제(들):

솔루션:

 

12. 문제(들):

솔루션:

 

13. 문제(들):

솔루션:

여기서는 파이썬 3에서 파이썬 2처럼 자동으로 비교하지 않으므로 int를 반환해야 합니다.

 

14. 문제(들):

솔루션:

 

15. 문제(들):

솔루션:

키를 문자열로 변환하여 ch가 이진 키의 int가 아닌 문자열이 되도록 했습니다. 파일을 참조하세요.

 

16. 문제(들):

TypeError: 'FileNotFoundError' 객체는 하위 스크립팅할 수 없습니다.

솔루션:

파이썬 3에서 FileNotFoundError는 서브 스크립트화할 수 없으므로 대신 errno 어트리뷰트인 e.errno를 사용하도록 변경되었습니다.

 

17. 문제(들):

솔루션:

이전에 완전히 정렬하는 정렬 함수로 인해 중첩된 사전/목록 비교가 작동하지 않던 것이 이제 사용할 수 없습니다. 딥디프 모듈과 딥디프 클래스를 사용하여 비교를 수행하세요.

 

18. 문제(들):

AttributeError: 모듈 '문자열'에 'replace' 속성이 없습니다.

솔루션:

문제를 해결하려면 아래 그림과 같이 직접 str 변수를 사용하여 대체하세요.

 

19. 문제(들):

솔루션:

str 또는 int 함수를 적절히 사용합니다.

 

20. 문제(들):

NameError: 이름 'cmp'가 정의되지 않았습니다.

솔루션:

딥디프 모듈과 딥디프 클래스를 사용하여 객체 비교를 수행합니다.

 

21. 문제(들):

솔루션:

위의 유형 오류 문제에 대해 아래와 같이 str을 int로 변환합니다.

—-

여기까지 파이썬 버전 2를 파이썬 버전 3으로 업그레이드할 때 주의해야 할 문제 목록에 대해 알아봤습니다. 향후 블로그 게시물에서 더 많은 학습 내용을 게시할 예정입니다. 그동안 마이그레이션에 행운을 빕니다!

 

더 읽어보기

다음 참고 자료가 도움이 되었습니다. 아래 참조 링크에서 더 자세한 내용을 읽고 Python 3으로의 코드 포팅을 개선할 수도 있습니다.

  1. https://www.python.org/dev/peps/pep-0373/
  2. https://wiki.python.org/moin/Python2orPython3
  3. https://www.toptal.com/python/python-3-is-it-worth-the-switch
  4. https://weknowinc.com/blog/running-multiple-python-versions-mac-osx
  5. https://docs.python.org/3/howto/pyporting.html
  6. https://wsvincent.com/install-python3-mac/
  7. http://python3porting.com/pdfs/SupportingPython3-screen-1.0-latest.pdf
  8. https://riptutorial.com/Download/python-language.pdf
  9. https://docs.couchbase.com/python-sdk/2.5/start-using-sdk.html
  10. https://docs.couchbase.com/c-sdk/2.10/start-using-sdk.html
  11. https://pypi.org/project/deepdiff/
  12. https://buildmedia.readthedocs.org/media/pdf/portingguide/latest/portingguide.pdf
  13. http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/promotions/python/python2python3.pdf

즐거운 시간 보내셨기를 바랍니다!

면책 조항: 이 문서는 포팅 문제 해결을 위한 완전한 가이드가 아니라 Python 3 업그레이드를 위한 빠른 참고 자료로 간주해 주세요. 여기서는 어느 정도 도움을 드리고 포팅 프로세스를 시작하는 데 도움을 드리고자 합니다. 도움이 될 만한 새로운 사실을 알게 되었다면 언제든지 공유해 주세요. 긍정적인 피드백을 보내주시면 감사하겠습니다!

 

중요한 의견과 피드백을 제공해주신 Raju Suravarjjala와 Keshav Murthy에게 감사드립니다.

 

작성자

게시자 Jagadesh Munta, 수석 소프트웨어 엔지니어, Couchbase

자가데시 문타는 미국 Couchbase Inc. 의 수석 소프트웨어 엔지니어입니다. 그 전에는 19년 동안 Sun Microsystems와 Oracle에서 함께 근무한 베테랑입니다. 미국 산호세 주립대학교에서 소프트웨어 공학 석사 학위를, JNTU에서 컴퓨터 공학 학사 학위를 받았습니다. 인도 JNTU에서 컴퓨터 과학 및 공학 학사 학위를 받았습니다. 그는 소프트웨어 개발자와 품질 자동화 엔지니어를 돕기 위한 "소프트웨어 품질 및 Java 자동화 엔지니어 생존 가이드"의 저자이기도 합니다.

댓글 남기기