소개
파이썬 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']))일반적인 딕셔너리/목록 비교는 아래를 참조하세요: 바이트 및 문자열을 값으로 사용합니다: |
string.replace(data[i],...) | data[i].replace(..) |
urllib.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으로 변환하는 몇 가지 샘플 명령어입니다. 마지막 명령에서는 모든 관용구가 적용되었다는 점에 유의하세요. 이렇게 하면 처음 변환할 때 주요 변경 사항을 처리할 수 있습니다.
1 2 3 4 5 6 |
(myenv) jmunta-mac:내 스크립트 jagadeshmunta$ 2to3 . -o new -n -w . hq-mac:테스트 러너 jagadeshmunta$ cd lib; mv lib/카우치베이스_도우미 ../카우치베이스_헬퍼 hq-mac:테스트 러너 jagadeshmunta$ 2to3 -f 모두 -f 버퍼 -f 관용구 -f set_literal -f ws_쉼표 -n -o ~/p3testrunner_3 -w . |티 ~/2to3_3.txt hq-mac:테스트 러너 jagadeshmunta$ 시간 2to3 -f 모두 -f 버퍼 -f 관용구 -f set_literal -f ws_쉼표 -n -w . |티 ~/2to3_4.txt $ 2to3 -f 모두 -f 버퍼 -f 관용구 -f set_literal -f ws_쉼표 -n -o ~/p3testrunner_helper -w ../카우치베이스_헬퍼 |티 ~/2to3_helper.txt cp -R ~/p3testrunner_helper/* . |
2. 수동 변경
자동 변환은 완전한 포팅을 수행하지 않습니다. 자동 변환 2to3 도구가 수행하는 일반적인 구문 변경보다 포팅 프로세스 중에 다음과 같은 일반적인 문제가 발생할 수 있습니다.
테스트 클래스를 실행하여 오류가 있는지 확인하고 적절하게 수정하여 바이트에서 문자열로 또는 문자열에서 바이트로 전환할지 또는 정렬된 함수의 키 이름을 수정해야 하는 정렬/비교 문제를 해결할지 결정합니다. 이 과정은 모든 코드 런타임의 유효성이 검사될 때까지 반복적으로 수행됩니다.
공통 패턴이 확실해지면 grep과 sed를 사용하여 여러 클래스 파일에서 바꿀 수 있습니다. 런타임까지 다른 코드에 대해 확실하지 않은 경우 해당 테스트 클래스가 실행될 때까지 연기하세요.
타사 라이브러리/모듈에 문제가 있거나 변경되었을 수 있으므로 웹에서 검색하여 적절하게 사용해야 합니다.
지원되는 모든 플랫폼과 매개변수에서 실행하여 모든 코드 경로가 포함되는지 확인하세요.
3. 런타임 검증 및 수정
변환이 완료되면 파이썬은 동적 언어이므로 많은 코드 런타임을 수행하세요. 그렇지 않고 시각적으로 정적 코드 검사/변경만 수행하면 변경 사항으로 인해 문제가 발생할 수 있습니다. 기본 정상 테스트, 수락 테스트부터 시작한 다음 단일 테스트 모듈에서 전체 테스트를 선택할 수 있습니다.
익숙해지면 다른 모든 모듈을 하나씩 적용하세요. 새 리포지토리에 변경 사항을 계속 체크인하세요. 또한 최신 빌드에서 정상 테스트를 실행하여 이 새 리포지토리에서 포팅된 변경 사항에 회귀가 없는지 확인해야 합니다. 또한 유효성 검사에는 Python 3에서 지원되는 모든 플랫폼이 포함되어야 합니다.
파이썬 3 포팅된 코드 및 상태
아래는 파이썬 3 포팅된 코드가 메인 리포지토리에 병합될 때까지 새 리포지토리를 찾을 수 있는 곳입니다. 계획은 한 주기의 포팅을 수행하거나 중간에 메인 리포지토리에서 변경 사항을 가져와 이곳으로 수동 병합하는 것입니다.
https://github.com/couchbaselabs/testrunner-py3/
(브랜치: 마스터)
다른 런타임 문제가 있을 수 있으므로 많은 일반적인 변경 사항이 이미 수행되었지만 완료되지 않았습니다. 또한 입력 값 유형 변환에 대한 가정으로 인해 공통 수정 사항이 이전 수정 사항으로 되돌아갈 수도 있습니다. 아직 파이썬 3에서 검증해야 할 포팅된 코드가 더 있으며 이 작업은 계속 진행 중입니다.
이제 일반적인 문제를 보여드리겠습니다. 발생한 런타임 유효성 검사 중입니다. 문제가 발생했을 때 이를 참조하여 비슷한 문제가 발생하는지 확인할 수 있습니다. 동일한 해결 방법을 적용하여 효과가 있는지 확인할 수 있습니다. 그리고 새로운 아이디어가 있다면 댓글에 적어주세요.
일반적인 런타임 문제
1. 문제(들):
- 런타임 중에 바이트 대신 문자열, 문자열 대신 바이트와 같은 아래 TypeError 중 일부가 발생할 수 있습니다.
- 오류#1. 유형 오류: 문자열을 바이트열로 연결할 수 없습니다.
- Error#2. TypeError: 바이트가 아닌 문자열이어야 합니다.
-
1234567파일 "lib/mc_bin_client.py", 라인 53, in __init__ 만약 msg: supermsg += ": " + str(msg)유형 오류: 필수 be str, not 바이트파일 "lib/mc_bin_client.py", 라인 141, in _recvMsg응답 += 데이터유형 오류: 필수 be str, not 바이트
-
- 오류#3. TypeError: 'str'이 아닌 바이트열과 유사한 객체가 필요합니다.
-
1234567891011121314151617181920파일 "lib/remote/remote_util.py", 라인 3038, in 로그_명령_출력 만약 "경고" in 라인 그리고 "거대한 페이지" in 라인:유형 오류: a 바이트-같은 객체 는 필수, not 'str'파일 "lib/tasks/task.py", 라인 1167, in 실행_높은_처리량_모드 raise 예외(rv["err"])예외: a 바이트-같은 객체 는 필수, not 'str'파일 "lib/mc_bin_client.py", 라인 936, in _set_vbucket self.vbucketId = (((zlib.crc32(키)) >> 16) & 0x7fff) & (self.vbucket_count - 1)유형 오류: a 바이트-같은 객체 는 필수, not 'str'파일 "lib/mc_bin_client.py", 라인 148, in _recvMsg마법 = 구조체.포장 풀기(">B", 응답[0:1])[0]유형 오류: a 바이트-같은 객체 는 필수, not 'str'파일 "lib/remote/remote_util.py", 라인 4560, in check_cmd 만약 out 그리고 command_output in out[0]:유형 오류: a 바이트-같은 객체 는 필수, not 'str'
-
- Error#4. TypeError: str과 비-str 인수를 혼합할 수 없습니다.
-
1234567파일 "lib/mc_bin_client.py", 라인 126, in _sendMsg self.s.보내기(msg + 추가 헤더 + 키 + val + 확장_메타_데이터)유형 오류: can't concat str 에 바이트파일 "/usr/lib64/python3.6/urllib/parse.py", 라인 120, in _coerce_argsraise 유형 오류("str 인자와 비-str 인자를 혼합할 수 없습니다.")유형 오류: 할 수 없음 믹스 str 그리고 비-str 인수
-
솔루션:
문에 있는 변수의 유형을 확인하고 xxx.encode()를 사용하여 바이트열을 가져오거나 xxx.decode()를 사용하여 문자열을 가져오거나 접두사 b를 사용하거나 str()을 사용하세요. 때로는 입력을 알 수 없는 경우가 있으며, 이 경우 AttributeError: pass를 제외하고 x.encode()를 사용하세요.
2. 문제(들):
TypeError: root - 오류 - --->설치 실패: 'str'이 아닌 바이트열과 같은 객체가 필요합니다.
솔루션:
이 경우 비교 대상 문자열에 접두사로 b를 추가하거나 바이트 유형을 문자열 유형으로 변경합니다. 예: lib/remote/remote_util.py
1 2 |
만약 o[0] != b"": o = o[0].분할(b" ") |
오류를 일으키는 정확한 줄을 확인하는 것을 제외하고는 시도-로 둘러쌉니다(예: 위의 TypeError).
1 2 3 4 5 6 7 8 9 10 11 |
가져오기 트레이스백 시도: .. 예외 예외 as e: 로그.정보("{}".형식(e)) 트레이스백.print_exc() exc_type, exc_obj, exc_tb = sys.exc_info() fname = os.path.분할(exc_tb.tb_frame.f_code.공동 파일 이름)[1] 인쇄(exc_type, fname, exc_tb.tb_lineno) |
traceback.print_exec() 뒤의 샘플 출력을 통해 자바처럼 전체 스택 추적을 확인할 수 있습니다.
아래와 같이 lib/remote/remote_util.py를 변경하여 수정합니다.
1 2 3 4 5 6 |
3079 에 대한 라인 in 출력: 3080 시도: 3081 라인=라인.디코딩() 3082 예외 속성 오류: 3083 통과 |
3. 문제(들):
1 2 3 |
파일 "lib/membase/api/rest_client.py", 라인 4178, in multiscan_count_for_gsi_index_with_rest 콘텐츠 = 콘텐츠.분할("[]")[0] 유형 오류: a 바이트-같은 객체 는 필수, not 'str' |
솔루션:
1 |
콘텐츠 = 콘텐츠.분할(b'[]')[0].디코딩() |
4. 문제(들):
일부 테스트 스위트에 대해 suite_setUp() 또는 suite_tearDown()이 누락되었습니다.
1 |
속성 오류: 유형 객체 'XDCRAdvFilterTests' has 아니요 속성 'suite_setUp' |
솔루션:
더미 suite_setUp() 및 suite_tearDown() 메서드를 추가합니다.
1 2 3 4 5 6 7 8 |
11a12,18 > > def suite_setUp(self): > 인쇄("*** XDCRAdvFilterTests : suite_Setup() ***") > > def suite_tearDown(self): > 인쇄("*** XDCRAdvFilterTests : suite_tearDown() ***") > |
5. 문제(들):
1 2 3 |
파일 "./testrunner.py", 라인 416, in 메인 결과.오류 = [(이름, e.메시지)] 속성 오류: 'AttributeError' 객체 has 아니요 속성 '메시지' |
솔루션:
1 |
결과.오류 = [(이름, str(e))] |
6. 문제(들):
속성 오류: '전송' 개체에 '_Thread__stop' 속성이 없습니다.
1 2 3 4 5 6 7 8 9 10 |
파일 "./testrunner.py", 라인 529, in 메인 t._Thread__stop() 속성 오류: '운송' 객체 has 아니요 속성 '_Thread__stop' 파일 "pytests/view/viewquerytests.py", 라인 45, in 중지 self._Thread__stop() 속성 오류: 'StoppableThread' 객체 has 아니요 속성 '_Thread__stop' self._stop() 유형 오류: '이벤트' 객체 는 not 호출 가능 |
솔루션:
데몬이 아닌 스레드를 직접 중지할 수는 없습니다. 하지만 구문상으로는 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
1 2 3 4 5 6 7 8 |
def 빌드굿셋(좋은 문자=문자열.인쇄 가능, badChar='?'): 143 """좋은 문자가 아닌 모든 문자를 변환하는 번역 테이블을 작성합니다. 144에서 나쁜 문자""" 145 모든 문자 = '\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./0123 456789:;?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~\x7f\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x9 3\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\x bb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\ xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff' 146 badchars = str.메이크트랜스(모든 문자, 모든 문자, 좋은 문자) 147 badchars1=str.번역(모든 문자,badchars) 148 rv = str.메이크트랜스(badchars1, badChar * len(badchars1)) 149 반환 rv |
8. 문제(들):
TabError: 들여쓰기에 탭과 공백이 일관성 없이 사용됨
1 2 3 4 |
파일 "pytests/security/audittest.py", 라인 396 shell = 원격 머신 셸 연결(self.마스터) ^ 탭 오류: 일관성 없음 사용 의 탭 그리고 공백 in 들여쓰기 |
솔루션:
탭 문자를 검색하고 공백 문자로 바꿉니다.
위 문제의 경우 탭 문자를 제거합니다.
1 |
sed -i 's/\t/ /g' 파이테스트/보안/감사 테스트.py |
9. 문제(들):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
파일 "lib/couchbase_helper/documentgenerator.py", 라인 83, in __next__ 값 = arg[seed % len(arg)] 유형 오류: 목록 인덱스 필수 be 정수 또는 슬라이스, not float 파일 "lib/membase/helper/bucket_helper.py", 라인 517, in load_some_데이터 키 = ["key_%s_%d" % (테스트, i) 에 대한 i in 범위(number_of_buckets)] 유형 오류: 'float' 객체 할 수 없음 be 해석 as an 정수 파일 "lib/membase/helper/bucket_helper.py", 라인 372, in 확인_데이터 테스트.assertEqual(값, 키, msg='값이 일치하지 않습니다') 어설션 에러: b'key_d918f450-5858-4430-a016-230e1f45bcf9_0' != 'key_d918f450-5858-4430-a016-230e1f45bcf9_0' : 값 dont 일치 파일 "pytests/setgettests.py", 라인 90, in set_get_테스트 self.테스트.실패("{0} 키의 값 불일치".형식(키)) 어설션 에러: 값 불일치 에 대한 키 9fcbd36f-e34d-477b-9fc5-0A5D067DFF4B 파일 "pytests/security/auditmain.py", 라인 320, in 반환 필드 정의 만약 (인스턴스((세부 정보['필수_필드'][항목.encode('utf-8')]), dict)): 키 오류: b'버킷_이름' 파일 "lib/tasks/task.py", 라인 2370, in _check_ddoc_개정 new_rev_id = self._parse_revision(메타['rev']) 키 오류: 'rev' |
솔루션:
대소문자 구분 문제. x_couchbase_meta 키에서 X_Couchbase_Meta로 변경하여 수정되었습니다.
10. 문제(들):
- Error#1. TypeError: 'dict'와 'dict'의 인스턴스 간에는 '<'가 지원되지 않습니다.
- Error#2. TypeError: 이 함수에 대한 잘못된 키워드 인수가 'cmp'입니다.
1 2 3 |
파일 "pytests/tuqquery/tuq_dml.py", 라인 455, in test_insert_with_선택 예상 결과 = 정렬됨([{버킷.이름: {'name': doc['name']}} 에 대한 doc in 값[:num_docs]]) 유형 오류: '<' not 지원 사이 인스턴스 의 'dict' 그리고 'dict' |
솔루션:
1 |
예상 결과 = 정렬됨(예상 결과,키=(람다 x: x[버킷.이름]['name'])) |
11. 문제(들):
1 2 3 |
파일 "pytests/tuqquery/tuq_2i_index.py", 라인 1057, in test_simple_array_색인 self.assertTrue(정렬됨(실제_결과_내['결과']) == 정렬됨(예상 결과['결과'])) 유형 오류: '<' not 지원 사이 인스턴스 의 'dict' 그리고 'dict' |
솔루션:
1 2 3 |
- self.assertTrue(정렬됨(실제_결과_내['결과']) == 정렬됨(예상 결과['결과'])) + self.assertTrue(정렬됨(실제_결과_내['결과'], 키=(람다 x: x['name'])) == \ + 정렬됨(예상 결과['결과'], 키=(람다 x: x['name']))) |
12. 문제(들):
1 2 3 4 5 6 7 |
파일 "pytests/tuqquery/tuq.py", 라인 1221, in _verify_results self.실패("결과가 올바르지 않습니다.실제 숫자 %s. 예상 숫자: %s.\n" % (len(실제 결과), len(예상 결과))) 어설션 에러: 결과 는 잘못된.실제 숫자 0. 예상 숫자: 72. 파일 "lib/tasks/task.py", 라인 3638, in filter_emitted_행 역방향=descending_set) 유형 오류: 'cmp' 는 an 유효하지 않음 키워드 인수 에 대한 이 함수 |
솔루션:
1 |
예상_행 = 정렬됨(self.emitted_rows, 키=(람다 x: (x['key'],x['id'])),역방향=descending_set) |
13. 문제(들):
1 2 3 |
파일 "lib/tasks/task.py", 라인 3675, in <listcomp> 예상_행 = [행 에 대한 행 in 예상_행 만약 행['key'] >= 시작_키 그리고 행['key'] <= end_key] 유형 오류: '>=' not 지원 사이 인스턴스 의 'int' 그리고 'NoneType' |
솔루션:
여기서는 파이썬 3에서 파이썬 2처럼 자동으로 비교하지 않으므로 int를 반환해야 합니다.
14. 문제(들):
1 |
hasattr(항목,'반복 항목') does't 반환 true |
솔루션:
1 2 3 4 5 6 7 8 |
@@ -754,7 +755,7 @@ 클래스 멤캐시드클라이언트(객체): # 딕셔너리인 경우 쌍 생성기로 변환합니다. 컬렉션 = self.컬렉션_이름(컬렉션) - 만약 hasattr(항목, 'iteritems'): + 만약 hasattr(항목, 'items'): 항목 = iter(항목.항목()) 만약 hasattr(항목, 'items'): |
15. 문제(들):
1 2 3 |
파일 "lib/crc32.py", 라인 78, in crc32_해시 crc = (crc >> 8) ^ crc32tab[int((crc ^ ord(ch)) & 0xff)] 유형 오류: ord() 예상 문자열 의 길이 1, 하지만 int 발견 |
솔루션:
키를 문자열로 변환하여 ch가 이진 키의 int가 아닌 문자열이 되도록 했습니다. 파일을 참조하세요.
1 2 3 4 |
시도: 키 = 키.디코딩() 예외 속성 오류: 통과 |
16. 문제(들):
TypeError: 'FileNotFoundError' 객체는 하위 스크립팅할 수 없습니다.
솔루션:
파이썬 3에서 FileNotFoundError는 서브 스크립트화할 수 없으므로 대신 errno 어트리뷰트인 e.errno를 사용하도록 변경되었습니다.
1 2 3 4 5 |
파일 "lib/remote/remote_util.py", 라인 1714, in create_디렉토리 만약 e[0] == 2: 유형 오류: '파일 찾을 수 없음 오류' 객체 는 not 구독 가능 - 만약 e[0] == 2: + 만약 e.errno == 2: |
17. 문제(들):
1 2 3 4 5 6 |
트레이스백 (대부분 최근 통화 마지막): 파일 "lib/couchbase_helper/tuq_helper.py", 라인 521, in 실행_쿼리_및_검증_결과 self._verify_results(정렬된_실제_결과, 정렬된_예상_결과) 파일 "lib/couchbase_helper/tuq_helper.py", 라인 114, in _verify_결과 raise 예외(msg) 예외: 그리고 숫자 의 행 일치 하지만 의 결과 불일치, 제발 확인 |
솔루션:
이전에 완전히 정렬하는 정렬 함수로 인해 중첩된 사전/목록 비교가 작동하지 않던 것이 이제 사용할 수 없습니다. 딥디프 모듈과 딥디프 클래스를 사용하여 비교를 수행하세요.
18. 문제(들):
AttributeError: 모듈 '문자열'에 'replace' 속성이 없습니다.
1 2 3 |
파일 "scripts/populateIni.py", 라인 52, in 메인 데이터[i] = 문자열.대체(데이터[i], '역동적', 서버[0]) 속성 오류: 모듈 '문자열' has 아니요 속성 'replace' |
솔루션:
문제를 해결하려면 아래 그림과 같이 직접 str 변수를 사용하여 대체하세요.
1 |
데이터[i].대체( '역동적', 서버[0]) |
19. 문제(들):
1 |
유형 오류: '>' not 지원 사이 인스턴스 의 'int' 그리고 'str' |
솔루션:
str 또는 int 함수를 적절히 사용합니다.
1 2 |
만약 where_clause: + where_clause = where_clause.대체('if t > "', 'if str(t) > "') #로 int, str 비교 간 유형 오류 수정 |
20. 문제(들):
NameError: 이름 'cmp'가 정의되지 않았습니다.
솔루션:
딥디프 모듈과 딥디프 클래스를 사용하여 객체 비교를 수행합니다.
21. 문제(들):
1 2 3 |
파일 "lib/couchbase_helper/tuq_helper.py", 라인 782, in verify_indexes_재배포 만약 cmp(items_count_before_rebalance, items_count_after_rebalance) != 0: NameError: 이름 'cmp' 는 not 정의 |
솔루션:
1 2 3 4 5 |
사용 딥디프 모듈 그리고 딥디프 클래스 에 do 객체 비교. - 만약 cmp(index_state_before_rebalance, index_state_after_rebalance) != 0: + 만약 딥디프(index_state_before_rebalance, 색인_sFile "lib/couchbase_helper/documentgenerator.py", 라인 19, in has_다음 반환 self.itr < self.끝 유형 오류: '<' not 지원 사이 인스턴스 의 'int' 그리고 'str' |
위의 유형 오류 문제에 대해 아래와 같이 str을 int로 변환합니다.
1 |
반환 int(self.itr) < int(self.끝) |
—-
여기까지 파이썬 버전 2를 파이썬 버전 3으로 업그레이드할 때 주의해야 할 문제 목록에 대해 알아봤습니다. 향후 블로그 게시물에서 더 많은 학습 내용을 게시할 예정입니다. 그동안 마이그레이션에 행운을 빕니다!
더 읽어보기
다음 참고 자료가 도움이 되었습니다. 아래 참조 링크에서 더 자세한 내용을 읽고 Python 3으로의 코드 포팅을 개선할 수도 있습니다.
- https://www.python.org/dev/peps/pep-0373/
- https://wiki.python.org/moin/Python2orPython3
- https://www.toptal.com/python/python-3-is-it-worth-the-switch
- https://weknowinc.com/blog/running-multiple-python-versions-mac-osx
- https://docs.python.org/3/howto/pyporting.html
- https://wsvincent.com/install-python3-mac/
- http://python3porting.com/pdfs/SupportingPython3-screen-1.0-latest.pdf
- https://riptutorial.com/Download/python-language.pdf
- https://docs.couchbase.com/python-sdk/2.5/start-using-sdk.html
- https://docs.couchbase.com/c-sdk/2.10/start-using-sdk.html
- https://pypi.org/project/deepdiff/
- https://buildmedia.readthedocs.org/media/pdf/portingguide/latest/portingguide.pdf
- http://ptgmedia.pearsoncmg.com/imprint_downloads/informit/promotions/python/python2python3.pdf
즐거운 시간 보내셨기를 바랍니다!
면책 조항: 이 문서는 포팅 문제 해결을 위한 완전한 가이드가 아니라 Python 3 업그레이드를 위한 빠른 참고 자료로 간주해 주세요. 여기서는 어느 정도 도움을 드리고 포팅 프로세스를 시작하는 데 도움을 드리고자 합니다. 도움이 될 만한 새로운 사실을 알게 되었다면 언제든지 공유해 주세요. 긍정적인 피드백을 보내주시면 감사하겠습니다!
—
중요한 의견과 피드백을 제공해주신 Raju Suravarjjala와 Keshav Murthy에게 감사드립니다.