보관물

작성자 보관물

Windows에서 pandas사용시 cx_Freeze로 build 후 실행시 ImportError: Missing required dependencies[‘numpy’] 해결 하는 방법

3월 24, 2017 댓글 남기기

문제 발생 환경 정보

  • Windows 8.1 K
  • Python 3.4.4 (32bit)
  • cx-Freeze 4.3.4
  • pandas 0.19.2
  • numpy 1.12.0

기존 application의 요건이 추가되어 pandas를 사용하게 되었다.
작업이 마무리 되어 cx_Freeze로 build를 수행할때까지는 별 문제가 없었지만 exe를 실행해보니 다음과 같은 error가 발생되었다.

cx_Freeze_numpy

결국은 ImportError: Missing required dependencies [‘numpy’] 가 발생한 것인데 build log를 살펴보면 정상적으로 numpy를 추출한 것 같기에 난감한 상황이 되었다.

먼저 setup.py의 buildOptions에 numpy를 명시적으로 적어 주어봤다.

buildOptions = dict(packages=[],
excludes=[‘tkinter’, ’email’, ‘html’, ‘http’, ‘unittest’, ‘urllib’, ‘ctypes’, ‘distutils’],
includes=[‘numpy’, ‘wx.xml’],
include_msvcr=True)

증상은 동일 했다.
packages에도 numpy를 넣어봤지만 역시나 동일한 증상이 발생되며 해결되지 않았다.

일단 찾아보니 cx_Freeze가 작년말(2016년 11월경) 커다란 update가 있었기도 했고 현재 5.0.1 version이 stable version이므로 cx_Freeze를 5.0.1로 재설치하여 다시 시도해 봤다.

문제 해결을 위해 재설치한 환경 정보

  • cx_Freeze 5.0.1

그런데…

ImportError: Missing required dependencies [‘_methods’]

어라? error message가 바뀌었다.
위에 적진 않았지만 error message를 자세히 보니 _methods는 numpy.core package에 있는 _methods.py 였다.
위에 includes에 추가한 numpy 처럼 동일하게 처리 해보았다.

buildOptions = dict(packages=[],
excludes=[‘tkinter’, ’email’, ‘html’, ‘http’, ‘unittest’, ‘urllib’, ‘ctypes’, ‘distutils’],
includes=[‘numpy’, ‘numpy.core._methods’, ‘wx.xml’],
include_msvcr=True)

그랬더니…

ImportError: Missing required dependencies [‘distutils’]

이젠 ImportError가 친근하게 느껴질 정도이다.
excludes에서 distutils를 제거해보니 이번엔 ctypes에서 ImportError가 발생했다.
반복하다 결국 ImportError는 다음과 같은 buildOptions에서 해결되었다.

buildOptions = dict(packages=[],
excludes=[‘tkinter’, ‘html’],
includes=[‘numpy’, ‘numpy.core._methods’, ‘wx.xml’],
include_msvcr=True)

cx_Freeze에서의 ImportError관련 부분은 글을 쓰는 현재 기준(2017.03.24) issue가 등록된 상태이다.

[관련 링크]
conda env: ImportError: Missing required dependencies [‘numpy’]
cx_Freeze 5.0.1 do not find some modules that cx_Freeze 5.0 did
Missing modules in numpy and other packages

위에서 언급하진 않았지만 cx_Freeze를 5.0.1로 변경하였더니 build시 module이 library.zip으로 압축되어 생기질 않았다.
죄다 folder로 풀려버리는 증상이 있었다.

cx_Freeze_module_out

cx_Freeze 5.x로 version up이 되면서 변경사항이 있었는데 이와 연관된 이유인것 같다.
(cx_Freeze release note의 2, 3번 항목 참조)

현재 사용할 수 있는 option중에 몇 가지 방법을 시도해 보다 결국 다음과 같은 식으로 해결을 했다.
다만 library.zip은 더이상 생성되지 않는다. 다만 module 폴더들이 사라진다.

buildOptions = dict(packages=[],
excludes=[‘tkinter’, ‘html’],
includes=[‘numpy’, ‘numpy.core._methods’, ‘wx.xml’],
zip_include_packages=[‘*’],
zip_exclude_packages=[‘numpy’, ‘numpy.core._methods’],
include_msvcr=True)

하지만 이렇게 해도 zip_exclude_packages에 정의한 module은 폴더가 남는다.
원래 module이 폴더로 풀려버리는 증상은 별도 post로 작성하려 했으나 zip_exclude_package 항목때문에 한 post에 묶을 수 밖에 없었다.

zip_exclude_packages에 numpy, numpy.core_methods를 추가하지 않으면 애초에 문제가 되었던 ImportError: Missing required dependencies [‘numpy’]가 다시 발생하게 된다.

현재 issue로 등록되어있듯이 cx_Freeze에서 module import와 관련된 부분 어딘가에 bug가 있는 것 같다.

카테고리:Python

[AWS] NoSuchMethodError : org.apache.http.ssl 오류 발생시 확인할 부분

1월 26, 2017 댓글 남기기

문제 발생 환경 정보

  • Spring Framework 3.2.3.RELEASE
  • org.apache.httpcomponents.httpclient 4.3.3

오류 사항

1월 26, 2017 3:58:25 오후 org.apache.catalina.core.StandardWrapperValve invoke

심각: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler processing failed; nested exception is java.lang.NoSuchMethodError: org.apache.http.conn.ssl.SSLConnectionSocketFactory.<init>(Ljavax/net/ssl/SSLContext;Ljavax/net/ssl/HostnameVerifier;)V] with root cause

java.lang.NoSuchMethodError: org.apache.http.conn.ssl.SSLConnectionSocketFactory.<init>(Ljavax/net/ssl/SSLContext;Ljavax/net/ssl/HostnameVerifier;)V

at com.amazonaws.http.conn.ssl.SdkTLSSocketFactory.<init>(SdkTLSSocketFactory.java:56)

at com.amazonaws.http.apache.client.impl.ApacheConnectionManagerFactory.getPreferredSocketFactory(ApacheConnectionManagerFactory.java:91)

at com.amazonaws.http.apache.client.impl.ApacheConnectionManagerFactory.create(ApacheConnectionManagerFactory.java:65)

at com.amazonaws.http.apache.client.impl.ApacheConnectionManagerFactory.create(ApacheConnectionManagerFactory.java:58)

at com.amazonaws.http.apache.client.impl.ApacheHttpClientFactory.create(ApacheHttpClientFactory.java:51)

at com.amazonaws.http.apache.client.impl.ApacheHttpClientFactory.create(ApacheHttpClientFactory.java:39)

at com.amazonaws.http.AmazonHttpClient.<init>(AmazonHttpClient.java:282)

at com.amazonaws.AmazonWebServiceClient.<init>(AmazonWebServiceClient.java:164)

at com.amazonaws.services.s3.AmazonS3Client.<init>(AmazonS3Client.java:520)

at com.amazonaws.services.s3.AmazonS3Client.<init>(AmazonS3Client.java:500)

at com.amazonaws.services.s3.AmazonS3Client.<init>(AmazonS3Client.java:482)

at com.amazonaws.services.s3.AmazonS3Client.<init>(AmazonS3Client.java:454)

at com.amazonaws.services.s3.AmazonS3Client.<init>(AmazonS3Client.java:436)

해결 방안

Apache Commons HTTP Client의 version이 낮아서 생긴문제이다.

AWS SDK는 최소 4.5.2를 요구한다고 한다.

관련 링크

https://github.com/aws/aws-sdk-java/issues/938

카테고리:AWS

[IEEE 754] 0.1 + 0.2 = 0.30000000000000004? 0.1 + 0.2 ≠ 0.3?

6월 30, 2016 댓글 남기기

Rounding Error

IEEE 754에 의해 floating point(부동소수점)을 표현하게 되는 경우 (정밀도에 따라)제한된 자릿수로 실수를 표현하게 된다. 예를들어 binary 32(single precision, 단정밀도)의 경우 가수부(significand)는 23 bit의 표현 범위를 갖는다.
그렇기 때문에 표현하려는 원래의 수가 가수부의 표현범위보다 자리수가 많다면 23 bit를 제외한 나머지는 반올림처리를 하여 잘라낼 수 밖에 없게 되는데 이때문에 부동소수점은 태생적으로 약간의 부정확성이 생길 수 밖에 없다.

binary(이진수)로 표현하는 것도 가수부의 표현범위와 연관되는 또 하나의 이유가 된다.
decimal(십진수)을 binary(이진수)로 표현하는 경우 무한히 반복되는 수가 될 수 있어 근사값 표현이 되기 때문이다.
예를 들어 십진수 0.1은 이진수로 표현하게 되면 0.00011001100110011… 이 되어 뒷부분의 0011이 무한히 반복되는 수가 된다. 이를 가수부영역에 표현하기 위해서는 반올림 처리를 해서 실제값과 가장 가까운 수로 표현할 수밖에 없게 된다.

0.1 + 0.2 = 0.30000000000000004?

대부분의 언어에서 0.1 + 0.2 = 0.30000000000000004를 표현하고 있다.
결론부터 말하자면 이런 결과는 IEEE 754표준 중 double precision floating point(배정도 부동소수점)를 사용하여 계산된 결과를 정밀도를 맞추기 위해 나머지 수를 반올림하여 표현되었기 때문이다.

Addition

반올림 오류가 발생하게되는 상황을 이해하기 위해 사칙연산 중 덧셈(addition)을 예를 들어 설명하고자 한다.

Addition rule

먼저 다음의 두 수를 더하는 부동소수점의 덧셈을 계산하는 기본적인 방법은 다음과 같다.

add_1.png

  • 지수부(exponent) q1과 q2 중 작은 값을 큰값과 같도록 맞춘다.
    이때 가수부(significand)는 변경되는 지수부에 의해 shift 처리한다.
    예를 들어 q1 < q2 라면 A의 q1값을 q2에 맞추고 이에 따라 A의 가수부 c1을 오른쪽으로 q2-q1만큼 shift한다.
  • 가수부끼리 덧셈을 계산한다.
  • 계산된 결과를 정규화(normalize)한다.
  • 가수부 bit에 맞도록 반올림 처리한다.

참고로 지수부를 동일하게 맞추고 가수부를 bit이동할때 주의할 점은 IEEE 754에서 bit표현시 정규화된 경우 가장 앞에 1이 숨겨진 bit(hidden bit)가 생략되어 있다는 것을 기억해야 한다.

계산 예시

위에서 언급했듯이 0.1+0.2의 결과에 대한 것은 binary64 형식인 배정도 부동소수점으로 계산을 해야하지만 계산의 단순함을 위해 single precision floating point(단정도 부동소수점, binary32)를 사용하기로 하고 이에따라 오차가 날 수 있는 상황인 0.1 + 0.6를 계산해 보려 한다.

참고로 설명을 위해 정밀도를 IEEE 754 표준이 아닌 수로 작게 줄여(예를 들어 정밀도를 4로 가정) 계산을 해볼 수도 있지만 어느정도의 표준과 동일한 상황을 확인해 보기위해 binary32를 선택하였다.
그러기 위해선 0.1 + 0.2가 아닌 다른 결과 값이 필요하기때문에 0.70000005가 발생하는 0.1 + 0.6를 선택하였다.

0.1 + 0.6 ≠ 0.7

0.1 + 0.6 = 0.7이 우리가 원하는 계산결과지만 부동소수점에서는 왜 0.7이 되지 않는지를 확인해볼 필요가 있다.
덧셈 규칙에 따라 계산하기 전에 먼저 IEEE 754에 따른 binary32 형식으로 각 수를 표현해 보면 다음과 같다.

add_2add_3.png

1. 지수부 맞추기

이제 계산 규칙에 따라 먼저 지수부의 숫자를 같도록 맞춰보면 0.6의 지수부는 -1, 0.1의 지수부는 -4로 0.6의 지수부가 더 크다. 그러므로 0.1의 지수부를 -1가 되도록 맞춘 후 그에 따른 가수부를 변경하면 다음과 같다.

add_4.png

지수부 -4를 -1로 변경하고 그에 따라 소수점을 이동시켰다.

2. 가수부 덧셈 계산

이제 두 수의 가수부를 더해보면 다음과 같다.

add_5.png

이를 정리하여 binary 32 형식으로 표현하면 다음과 같다.

add_6.png

3. 계산된 결과를 정규화

계산될 결과가 이미 1.으로 시작하고 있어 이미 정규화가 되어있기 때문에 정규화 작업은 하지 않아도 된다.
만약 계산 결과가 다음과 같았다면 정규화를 진행해야한다.

add_7.png

4. 가수부 정밀도 맞추기

binary 32(단정도 부동소수점)의 가수부 bit 수는 23개이다. 현재 계산된 결과는 26개의 bit로 표현되어야 하므로 뒤의 3 bit를 반올림하여 버려야한다.
(사실 소수점 앞까지 하면 27 bit지만 IEEE 754 표준에 의해 가장 앞의 1은 숨겨진 bit로 처리하기 때문에 실제 bit표현시에는 bit에 담을 필요가 없다.)

add_8.png

정밀도를 맞추기 위해 반올림 처리를 해야하는데 IEEE 754에서는 Round to nearest, tites to even 을 기본으로 하고 있다.
반올림 할 값이 101이므로 이는 올림처리가 되어야한다. 그러므로 반올림 처리한 결과는 다음과 같다.

add_9.png

이를 정리하여 binary 32 형식으로 표현하면 다음과 같다.

add_10.png

덧셈 계산은 끝났다. 위의 결과를 십진수로 표현했을때 어떻게 되는지 확인해 보면 0.7이 아닌 0.70000005가 된다.

마찬가지 이유로 인해 글 제목과 같이 0.1 + 0.2를 double precision floating point(배정도 부동소수점)으로 계산해보면 0.3이 아닌 0.30000000000000004이 된다.
참고로 0.1 + 0.2를 single precision floating point(단정도 부동소수점)으로 계산한다면 0.3이 나온다. 이는 정밀도에 따른 차이로 단정도에서 오차가 발생하지 않는다고 해서 배정도에도 오차가 발생하지 않는다는 것을 뜻한다.
반대로 위의 예시였던 0.1 + 0.6은 single precision floating point에서는 0.70000005가 되지만 double precision floating point에서는 0.7로 정확하게 계산된다.

결론

부동소수점 연산시 오차가 발생하는 이유에 대해서는 서두에 요약하여 언급을 했듯이 반올림으로 인해 오차가 발생하기 때문이다.
참고로  (완벽하진 않지만) 최대한 정확한 결과를 얻기위해서는 몇가지 방법이 있다.

  • 이진수 형태(base가 2인)의 부동소수점보다는 십진수(base가 10인) 부동소수점을 사용한다.
    이렇게 하면 정밀도 자리수에 따른 반올림 오류는 여전히 존재하겠지만 적어도 십진수를 이진수로 변환할때 무한한 수가 되는 상황은 해결할 수 있다.
    예를들어 Java의 경우 float, double보다는 Decimal, BigDecimal 을 사용하면 된다.
  • 정밀도가 보다 높은 부동소수점을 사용한다.
    binary 32를 사용한다면 binary 64를 decimal 64를 사용한다면 decimal 128을 사용하면 정밀도가 높아지므로 연산에 의한 오차가 작아지게 된다.
  • 가능하면 부동소수점 연산을 사용하지 않는다.
    예를 들어 1.0 + 0.1 + 7을 계산해야한다고 하면 이를 모두 정수형태로 변형하기 위해 모든 수에 10을 곱하여 10 + 1 + 70으로 계산하고 계산된 결과를 다시 10으로 나누어 실수형태로 표현한다.

[참고자료]

Floating Point MathFloating Point Math

NUM04-J Do not use floating-point numbers if precise computation is required

카테고리:knowledge

[IEEE 754] floating-point(부동소수점)에 대하여

6월 24, 2016 8개의 댓글

IEEE 754는 IEEE에서 제정한 floating point(부동소수점)을 표현하는것에 대한 기술표준이다.
글을 쓰는 현재의 최신 version은 2008년 8월에 제정한 IEEE 754-2008이다.
이전에는 IEEE 754-1985는 binary floating point에 대한 표준을, IEEE 854-1987은 radix-independent floating point에 대한 표준(binary/decimal)을 정의했었지만 IEEE 754-2008에서는 이진법과 십진법을 모두 포함하고 있다.

IEEE 754 표준 정의

IEEE 754에서 정의하고 있는 주요 항목은 다음과 같다.

  • 산술 형식(Arithmetic formats)
  • 형식의 교환 (Interchange formats)
  • 반올림 규칙 (Rounding rules)
  • 연산 (Operations)
  • 예외 처리 (Exception handling)

이 외에도 고급 예외 처리, 추가 연산(삼각 함수 등) 등의 표준 또한 포함하고 있다.

Arithmetic formats

floating point(부동 소수점)은 실수를 표현할때 소수점의 위치를 나타내는 지수와 유효숫자를 표현하는 가수로 나누어 표현한다.
유한한 수외에도 무한대와 NaN에 대해서 표현할 수 있도록 표준을 제시하고 있다.

기본 형식

ArithmeticFormat

floating point에 대한 표현 방식은 위와 같다.

s : 부호부(sign)를 표현하며 0인 경우 +, 1인 경우 -를 나타낸다.
c : 가수부(significand, fraction, mantissa)를 나타내며 양의 정수로 표현된다. 정밀도(precision)에 따라 범위가 제한된다.
b : 밑수(base)/기수(radix)를 나타내며 IEEE 754에서는 2 또는 10이 된다. 이는 각각 2진수, 10진수 표현이 되는것을 의미한다.
q : 지수부(exponent)를 나타내며  지수부는 소수점의 위치를 나타내게 된다.

예를 들자면 1.2345를 밑수가 10인 경우로 표현을 한다면 다음과 같다.

decimalexam.png

기본 형식에 의해 각 부분의 값은 다음이 된다.

s : 0
c : 12345
b : 10
q : -4

실제 표현시에는 IEEE 754에서 정한 정밀도(precision)에 따라 가수부(significand)와 지수부(exponent)의 bit size가 달라지므로 표현하는 숫자의 자릿수가 달라지게 된다.

NaN (Not a number)

IEEE 754에서는 일반적인 수외에 특별한 값을 정의하고 있다.
NaN은 연산과정에서 잘못된 입력을 받아 계산을 하지 못했음을 나타내는 기호다.
NaN이 발생하는 주요 상황은 다음과 같다.

NaN.png

NaN을 표현하는 방식은 다음과 같다.

  • 지수부(exponent)의 모든 bit는 1로 채운다.
  • 가수부(significand)의 값은 0이 아니어야 한다.
  • 부호부(sign)은 의미를 두지 않는다.

두 가지 종류로 구분되며 quiet NaN과 signaling NaN이 있다.

Quiet NaN

Quiet NaN은 잘못된 입력으로 인해 예외를 발생시키지 않고 NaN을 반환하여 연산을 지속시키는 역할을 한다.
Quiet NaN의 경우 가수부의 모든 bit를 1로 채운다.

Signaling NaN

Signaling NaN은 quiet NaN과는 반대로 잘못된 연산시에 예외를 발생시키는 경우를 나타낸다.
Signaling NaN은 가수부의 대부분의 bit를 0으로 채우고 최소 1개의 bit를 1로 채운다.

무한대

무한대는 overflow가 발생하였을때 표현하는 값을 정의한다.
이는 표현 가능한 최대의 수를 무한대로 사용하는 것보다 안전한 방법이기 때문이다.
무한대를 표현하는 방식은 다음과 같다.

  • 지수부(exponent)의 모든 bit는 1로 채운다.
  • 가수부(significand)의 모든 bit는 0으로 채운다.
  • 부호부(sign)에 따라 양의 무한대와 음의 무한대로 구분된다.

예를 들어 0 / 0은 NaN이 된다.
하지만 0이 아닌 수를 0으로 나누게 되면 무한대가 발생하게 되는데 1 / 0 = ∞, -1 / 0 = -∞가 된다.
IEEE 754에서는 c 가 0이 아닐때 c / 0 = ±∞로 정의하고 있다.
이때 부호는 c의 부호를 따라가게 된다.
참고로 부호부의  bit가 0이면 양의 무한대, 1이면 음의 무한대가 된다.

Signed zero

IEEE 754에서는 부호가 있는 0을 구분하고 있다.
단 if (x == 0)과 같은 작업에서 불확실한 결과를 낼 수 있기 때문에 -0 = +0 이라는 규칙을 정해놓았다.
부호 있는 0을 사용하게 되면 1 / -∞ < 1 / +∞ 와 같은 표현이 가능하게 된다.
부호 있는 0을 표현하는 방식은 다음과 같다.

  • 지수부(exponent)의 모든 bit는 0으로 채운다.
  • 가수부(significand)의 모든 bit 역시 0으로 채운다.
  • 부호부(sign)에 따라 +0 과 -0으로 구분된다.

참고로 부호부의 bit가 0이면 +0, 1이면 -1이 된다.

Interchange formats

IEEE 754에서는 기본적으로는 32, 64, 128 bit의 binary 형식과 64, 128 bit의 decimal 형식을 정의하고 있다.
참고로 binary 32형식은 단정도(single precision), binary 64 형식은 배정도(double precision)라 한다. 각각의 형식에 대한 주요 인자들은 다음과 같다. (sign bit는 항상 1자리)

format.png

참고로 binary 형식의 경우 각 자릿수는 bit수와 동일하지만 decimal의 경우에는 표현하는 숫자의 자릿수를 나타내기때문에 실제 bit와는 차이가 있다. 또한 decimal 64decimal 128를 bit로 표현하는 방식이 약간 다르다.

이외에도 binary 16, binary 256, decimal 32를 정의하고 있다.
또한 기본 형식을 확장 하는 형식 역시 정의하고 있다. 확장 형식(extended precision format)은 표준 형식에서 얼마나 더 많은 bit를 추가해야 하는지에 대한 하한선만을 정하고 있다.
주요 확장 형식에는 x86 확장 배정도 등이 있다.

형식 변환(binary32)

임의의 실수를 IEEE 754표준인 binary32 (single precision, 단정도)로 표현을 하기 위해서는 실수의 절대값을 이진법(binary)로 변환한 후 부호부, 지수부, 가수부에 해당하는 값을 정리하여 정해진 위치에 표현하면 된다.
기본적으로는 다음의 단계를 거친다.

  • 먼저 임의의 실수에서 부호부를 bit로 표현한다. (0 은 +, 1은 -)
  • 절대값을 이진법으로 표현한다.
  • 정규화(normalize) 처리를 하여 산술표현 형식으로 만든다.
    ArithmeticFormat
  • 위의 결과에서 가수부(c)의 가장 앞의 1을 제외한 나머지를 가수부(significand) bit에 채운다.
    (이때 모자라는 부분은 0으로 채운다.)
  • 지수부(q)는 bias값을 더한 후 이진법으로 표현하여 지수부(sign) bit에 채운다.

좀 더 자세한 내용은 아래 표현 예시를 통해 확인해 본다.

표현 예시

임의의 실수 -12.375를 binary32 형식으로 표현해 본다.
binary32의 bit 구성은 위의 표에 의하면 가수부 23, 지수부 8, 부호부 1가 필요하므로 이를 도식으로  나타내면 다음과 같다.

binary32.png

먼저 임의의 실수에서 부호부를 bit로 표현하면 -12.375는 음수이므로 부호부(sign)의 bit 값은 1이 된다.

binary32_1.png

절대값 12.375를 이진법으로 표현하면 1100.011이 된다.
참고로 이진법으로 변환할 때 소숫점 앞의 정수부는 나머지가 2보다 작을때까지 나눈 나머지들로 표현을 하고 소숫점 뒤의 소수부는 결과가 1.0이 될때까지 2를 곱하여 각 단계별 정수부로 표현을 한다.

이제 결과를 정규화(normalize) 한다. 정규화란 산술표현시 가수부(c)의 맨 앞자리가 1이 되도록 처리하는 것을 뜻한다. 정규화가 되면 가수부(c)는 1.xxxx 식으로 표현된다.
앞의 결과를 정규화하면 다음과 같다.

binary32_2.png

정규화를 하게되면 가수부의 정수부는 항상 1이 되므로 binary32 표현시 생략한다.
binary32 형식은 가수부가 23 bit로 구성되어있지만 정규화 작업에 의해 가장 앞의 1은 생략하여 표현하므로 실제로는 24bit를 표현하고 있는 것이다. 이러한 방식을 숨겨진 bit(hidden bit)를 사용한다고 말한다.
이제 가수부를 표현하면 다음과 같다.

binary32_3.png

1.10011에서 가장 앞의 1을 제외한 소수부만 표현을 하면되고 남은 bit는 모두 0으로 채운다.

이제 지수부만 남았다. 지수부는 양수/음수 모두 가능하기 때문에 이를 표현하는 특별한 방법을 사용하는데 IEEE 754에서는 bias 표현을 사용하여 양수와 음수를 표현한다.
binary32 형식에서 지수부는 8 bit로 구성되어있고 최소값은 -126이고 최대값은 127을 갖는다.
8 bit로 표현가능한 값은 0 ~ 255이기때문에 이를 반으로 나누어 양수와 음수를 표현하는 것이다.

즉, bias + q = 지수부(exponent)가 된다.

본 예시에서는 q = 3이므로 bias + q = 127 + 3 = 130이 된다.
130을 이진법으로 표현하면 10000010이다. 이제 마지막으로 지수부를 채워 binary32로 표현하면 다음과 같다.

binary32_4.png

Denormalized (비정규화된 수)

IEEE 754에서는 NaN, 무한대 등과 같이 특별한 값이 하나 더 있다.
위의 표현 예시에서 보면 정규화를 통해 binary32를 표현하였는데 이때 가장 앞의 1을 제외하고 bit값을 채워넣어 표현하였다.
다시 말하면 정규화하여 표현된 모든 수는 숨겨진 bit로 인해 가수부가 항상 1.xx..xx 인 수를 표현 할 수 밖에 없다.
예를 들어 denormal_1.png 보다 작은 denormal_2.png의 경우 지수부의 표현범위를 벗어나므로 표현 할 수 가 없게된다.
또한 이렇게 아주 작은 값일 경우 일부 수식에서 오류가 발생할 수도 있다.
그래서 IEEE 754에서는 비정규화된 수(Denormalized numbers)를 도입하여 이를 해결하고 있다.
비정규화된 수를 사용한 동작을 점진적 언더플로우(gradual underflow)라고 부른다.
비정규화된 수를 표현하는 방식은 다음과 같다.

  • 지수부(exponent)의 모든 bit는 0으로 채운다.
  • 부호부(sign)와 가수부(significand)의 값을 표현한다.

Rounding rules

IEEE 754에서는 floating-point 연산(혹은 변환)시 가수부(significand) 표현 범위를 넘어가는 경우 보다 원본값과 가장 가까운 값의 표현을 위해 반올림을 처리하게 된다.
IEEE 754에서는 다음의 다섯가지 종류의 반올림 방식을 정의하고 있다.

round up

round up은 반올림 처리시 +∞ 방향으로 올림처리를 한다.
그렇기때문에 음수인 경우에는 0의 방향으로 향하기때문에 절대값을 기준으로 본다면 숫자가 버림처리가 된다.

roundup

round down

round down은 반올림 처리시 -∞ 방향으로 내림처리를 한다.
그렇기 때문에 음수인 경우에는 절대값 기준으로 본다면 숫자가 올림처리가 된다.

rounddown.png

round toward zero

round toward zero는 반올림 처리시 항상 0의 방향으로 가장 가까운 숫자를 선택한다.
절대값을 기준으로 본다면 원래의 값보다 절대값이 작거나 같은 값 중에 가장 큰 숫자를 선택하게 된다. 즉 항상 버림처리가 된다.

roundzero

round to nearest, ties to even

round to nearest는 말 그대로 가장 가까운 값으로 반올림을 하는 것인데 IEEE 754에서는 가장 가까운 값의 기준으로 두 가지로 분류했다.
하나는 ties to even으로 가장 가까운 값이 2개인 경우( 예를 들어 0.5인 경우 가장 가까운 값은 0과 1) 가수부의 마지막 자리가 짝수인 값을 선택하는 것이다.
round to nearest, ties to even은 banker’s rounding이라고도 부르며 IEEE 754 표준에서는 rounding 처리에 대한 기본 방식으로 제시하고 있다.

roundeven.png

round to nearest, ties to even은 가장 가까운 값이 2개인 경우 짝수(even)을 향하게 되므로 화살표의 방향성은 다음과 같이 달라질 수도 있다.

roundeven2.png

round to nearest, ties away from zero

또하나의 방식으로는 ties away from zero가 있습니다. 이는 가장 가까운 값이 2개인 경우 절대값 기준으로 가장 큰값을 선택한다.

roundtieawayzero.png

Operations

IEEE 754에서는 floating point(부동 소수점) 표현외에도 산술 연산, 변환, 테스트 등에 관련된 표준을 정의하고 있다.
산술 연산의 경우 연산이 먼저 계산된 후 반올림(round to nearest, ties to even) 처리를 하도록 되어있다. 또한 거듭제곱, 나머지, 부호 처리 등에 대한 기준도 제시하고 있다.
왜냐하면 표준에 따르는 프로그램들 사이에서는 항상 동일한 결과를 얻을 수 있게 보장하는 것과 이식성(portability)을 높이기 위함이다.

Exception handling

IEEE 754에서는 각종 상황에 따라 예외가 발생하는 경우 이를 처리하는 handler를 사용하는 것을 정하고 있다. 기본적으로는 5개의 예외 상황을 정하고 있다.

  • Invalid operation (잘못된 연산)
    연산시에 잘못된 인자가 사용되는 경우에 발생하며 기본적으로는 NaN을 반환한다.
  • Division by zero (0으로 나누기)
    피 연산자가 0인 경우에 발생하며 기본적으로는 ±∞를 반환한다.
  • Overflow
    반올림 처리 후 표현범위를 벗어날때 발생하며 기본적으로는 ±∞를 반환한다.
  • Underflow
    반올림 처리 후 표현범위보다 너무 작은 값이 될때 발생하며 기본적으로는 비정규화된 수를 반환한다. 보통 inexact(부정확함)과 같이 발생된다.
  • Inexact (부정확함)
    연산의 결과가 부정확할 때 발생한다. 부정확하다는 것은 반올림 처리시 0이 아닌 수가 잘리는 상황이 발생할때가 대부분이다. 기본적으로는 반올림 처리된 결과를 반환한다.

또한 각각의 예외 상황을 정확하게 판단하기 위해 각각 1개의 상태 flag를 할당하여 예외 처리를 진행한다.

이 외에도 decimal floating point를 위해 clamped(exponent에 표현할 값이 범위를 벗어나는 경우 발생)와 Rounded(반올림시 숫자가 잘릴때, 만약 Rounded가 발생했는데 0이 아닌 수가 잘렸다면 Inexact가 발생된다.)를 추가로 정의하고 있다.

참고 자료

IEEE floating-point, wiki

IEEE 754, wiki (한국어)

What every computer scientist should know about floating-point arithmetic (english)

What every computer scientist should know about floating-point arithmetic (번역본)

NUM04-J Do not use floating-point numbers if precise computation is required

Programming in Java – 9.1 Floating point

IEEE 754 요약정보, 메아리 풉;

Floating Point Rounding

Rounding Algorithms

NaN, wiki

decimal64 floating-point format

decimal128 floating-point format

카테고리:knowledge

Windows에서 pysftp사용시 cx_Freeze하면 cryptography관련 오류가 발생하는 경우 해결 방법

5월 19, 2016 댓글 남기기

문제 발생 환경 정보

  • Windows 8.1 K
  • Python 3.4.4 (32bit)
  • pysftp 0.2.8
  • cryptography 1.3.2
  • pycrypto 2.6.1
  • paramiko 2.0.0

pysftp를 이용해 아주 간단한 in-house tool을 만들던 중 개발환경에서 바로 실행을 하면 문제가 없던 부분이 packaging을 하니 오류가 발생하는 상황이 발생하였다.

with pysftp.Connection(host=p_host, username=p_username, password=p_password) as sftp:

pysftp의 Connection을 사용하는 부분에서 오류가 발생했고 except로 오류를 잡아 확인해 보니 다음과 같은 오류 메시지가 발생하였다.

Multibackend cannot be initialized with no backends.
If you are seeing this error when trying to use default_backend()
please try uninstalling and installing cryptography

오류 메시지 대로 pip로 cryptography를 다시 설치해 봤지만 문제는 해결되지 않았다.

pysftp는 paramiko에 의존성이 있으므로 paramiko의 debug log를 찍어 좀 더 확인해 보기로 했다.
관련된  source에 다음의 code를 추가하여 log를 확인하였다.

import paramiko
paramiko.util.log_to_file(‘logs/paramiko.log’)

log 내용을 보면 paramiko.transport에서 오류가 시작되었고 호출된 것을 따라가보니
cryptography.hazmat.backends.multibackend의 Multibackend class에서 처음 오류메시지를 발생시키고 있었다.
문제되는 source는 찾았지만 뚜렷한 방법을 찾지 못하던 중 paramiko의 version을 낮춰서 해결했다는 글을 찾을 수 있었다.

paramiko의 changelog를 보면 현재 stable인 2.0.0은 하위호환성이 유지되지 않는다는 내용이 있다.

Warning: This is a backwards incompatible change.

참고로 paramiko 2.0.0은 2016.04.28에 version up 되었지만 pysftp 0.2.8은 2014.05.28이 마지막 release였다.
pip로 pysftp를 설치하게 되면 자동으로 paramiko 2.0.0이 설치되는데 아마도 이번 오류가 아니었다면 신경도 쓰지 않았었을 것 같다.
그렇기때문에 version을 낮추면 해결된다는 것이 어느정도 일리가 있어보이기도 하고 이전에 cx_Freeze의 문제로 python의 version을 낮추어 해결한 적이 있으므로 바로 실행에 옮겨보았다.
paramiko의 1.x 마지막 stable version은 1.17.0이기때문에 1.17.0 version을 설치하였다.

pip uninstall paramiko
pip install paramiko==1.17

그런데 설치가 되지 않았다.

error: Microsoft Visual C++ 10.0 is required (Unable to find vcvarsall.bat)

이전에 DLL관련 문제가 있어서 Microsoft Visual C++ Redistributable package를 몇가지 종류별로 설치해 두었었는데 그때와는 또 다른 상황이다.
이전에는 실행 중 발생하던 오류였다면 이번엔 package를 설치하는 과정에서 발생된 문제이다.

관련해서 구글링을 해보던 중 redistributable package가 아닌 Visual C++ 2010 Express를 설치해야한다는 글이 여러건 발견되어서 Visual C++ 2010 Express 설치본을 찾아 설치하고 다시 paramiko를 설치하니 정상적으로 설치가 되었다.
참고로 python 2.7과 python 3.4를 사용하는 경우 windows에서 module 설치시 Unable to find vcvarsall.bat관련 오류에 대해 잘 정리해 놓은 글이 있어 공유한다.

이제 실행을 해보니 이번엔 다음과 같은 오류가 발생되었다. 산넘어 산이다.

Traceback (most recent call last):
 File “C:/Users/imac/Project/Nuri/contentsUploader/main.py”, line 7, in <module>
  from vs import state
 File “C:\Users\imac\Project\Nuri\contentsUploader\vs\state.py”, line 2, in <module>
   import pysftp
 File “C:\Users\imac\Python3_4_4\lib\site-packages\pysftp.py”, line 10, in <module>
   import paramiko
 File “C:\Users\imac\Python3_4_4\lib\site-packages\paramiko\__init__.py”, line 30, in <module>
   from paramiko.transport import SecurityOptions, Transport
 File “C:\Users\imac\Python3_4_4\lib\site-packages\paramiko\transport.py”, line 50, in <module>
   from paramiko.dsskey import DSSKey
 File “C:\Users\imac\Python3_4_4\lib\site-packages\paramiko\dsskey.py”, line 26, in <module>
   from Crypto.PublicKey import DSA
 File “C:\Users\imac\Python3_4_4\lib\site-packages\Crypto\PublicKey\DSA.py”, line 89, in <module>
   from Crypto import Random
 File “C:\Users\imac\Python3_4_4\lib\site-packages\Crypto\Random\__init__.py”, line 28, in <module>
   from Crypto.Random import OSRNG
 File “C:\Users\imac\Python3_4_4\lib\site-packages\Crypto\Random\OSRNG\__init__.py”, line 34, in <module>
   from Crypto.Random.OSRNG.nt import new
 File “C:\Users\imac\Python3_4_4\lib\site-packages\Crypto\Random\OSRNG\nt.py”, line 29, in <module>
   import winrandom
ImportError: No module named ‘winrandom’
Process finished with exit code 1

winrandom을 찾을 수 없다는 얘긴데 pycrypto module에서의 bug였다.
현재는 fix된 source가 최종 release version에 포함되어 있지 않으므로 해당 부분의 소스를 직접 수정 하여 처리하였다. (글을 쓰는 현재 기준 stable version은 2.6.1)

Python3_4_4\Lib\site-packages\Crypto\Random\OSRNG\nt.py 파일의
28 line을 import winrandom 에서 from Crypto.Random.OSRNG import winrandom으로 수정하여 모든 문제를 해결하였다.

카테고리:Python

Windows에서 cx_Freeze로 packaging한 exe실행시 wxLocale관련 오류 해결 방법

4월 20, 2016 1개의 댓글

문제 발생 환경 정보

  • Windows 8.1 K
  • Python 3.5.1 (32bit)
  • wxPython-Phoenix 3.0.3.dev1964+f780b21
  • cx_Freeze 5.0

Python 3.5.1을 사용하기 위해 cx_Freeze 5.0을 이용해 Windows에서 packaging을 하니 sqlite3쪽에서 DLL load failed가 발생하거나 Windows 7에서의 경우는 api-ms-win-core-kernel32-private-l1-1-0.dll이 없다고 하거나 하는 등의 오류가 발생해서 다양한 방법을 시도해보았으나 결국 실패하였다.
(특이한 점은 python main.py와 같은 식으로 직접 실행하면 문제가 없지만 packaging한 exe를 실행할때만 발생한다는 것이다.)
이런 현상은 cx_Freeze뿐만아니라 PyInstaller로 packaging하는 경우도 비슷한 현상이 발생한다.
그래서 굳이 Python 3.5.1을 유지할 필요는 없어 3.4.4로 낮추고 cx_Freeze역시 stable version으로 낮춰 packaging을 하고 실행하였더니 다음과 같은 error가 발생하였다.

Python version을 낮춘 환경 정보

  • Windows 8.1 K
  • Python 3.4.4 (32bit)
  • wxPython-Phoenix 3.0.3.dev1964+f780b21
  • cx_Freeze 4.3.4

cx_Freeze_locale_error

wxLocale을 사용하지 않고 setlocale()을 바로 호출해서 C/C++과 windows locale간에 일치하지 않는다는 내용인데 구글링해보니 생각보다 쉽게 해결되었다.

http://stackoverflow.com/questions/21444951/wxpython-3-0-breaks-older-apps-locale-error

글 내용을 보면 locale정보를 명시적으로 적어주면 해결된다는 애기인지라 현재 source에서 locale설정 부분을 추가해서 packaging을 해보니 error없이 정상적으로 실행되었다.

app = wx.App()
locale = wx.Locale(wx.LANGUAGE_KOREAN)  #추가한 부분
frame = MainFrame(None)
frame.Show(True)
app.MainLoop()

참고로 locale관련된 정보는 wxPython-Phoenix의 Langauge page에서 확인 가능하다.

카테고리:Python

Python 3.5.x에서 cx_Freeze 설치하기

4월 19, 2016 댓글 남기기

wxPython-Phoenix를 사용하여 만든 application을 배포하기 위해 몇가지 방법을 찾아보다 결국 cx_Freeze를 사용하기로 하였다.
현재 기준으로(2016.04.19) cx_Freeze는 release version기준으로 4.3.4까지 나와있다.

당연히 pip를 사용해 해당 module을 설치할 수 있다.

pip install cx_Freeze

하지만 이렇게 설치한 cx_Freeze 4.3.4는 python 3.4까지만 지원을 하기 때문에 현재 개발환경인 python 3.5.1에서는 정상적으로 packaging이 되지 않았다.
좀 더 자세하게 얘기하면 packaging은 되지만 실행을 해보면 알수없는 오류와 함께 실행되지 않는다.

그래서 cx_Freeze를 python 3.5에서 사용할 수 있는 방법을 찾아보다 보니 cx_Freeze 5.0 for Python 3.5 on Windows 글을 찾게 되었다.
글 내용을 보면 2016년 4월 현재 stable version인 cx_Freeze 4.3.4는 Python 3.5를 지원하지 않지만 development version인  cx_Freeze 5.0은 Python 3.5를 지원한다는 내용이 서두에 있다.

글 내용은 Windows관련 내용이지만 cx_Freeze source code를 내려받아 Mac OS X에서도 설치해서 사용해보니 결과적으로 packaging도 잘되고 실행도 잘 되었다.

이번 post에서는 Mac OS X과 Windows에서 설치하는 방법을 모두 정리해보려 한다.

[Max OS X]

  1. cx_Freeze의  bitbucket에서 현재 source를  download한 후 압축을 푼다.
  2. 해당 폴더로 이동한 후 cx_Freeze를 설치한다.

    $ python setup.py install
    running install
    running bdist_egg
    running egg_info
    creating cx_Freeze.egg-info
    writing cx_Freeze.egg-info/PKG-INFO
    …중략…
    Installed /Users/imac/.pyenv/versions/3.5.1/lib/python3.5/site-packages/cx_Freeze-5.0-py3.5-macosx-10.10-x86_64.egg
    Processing dependencies for cx-Freeze==5.0
    Finished processing dependencies for cx-Freeze==5.0

  3. pip로 보면 5.0이 설치된 것을 확인할 수 있다.

    $ pip list
    …중략…
    cx-Freeze (5.0)
    …후략…

[Windows]

windows용은 두 가지 방법이 있다.

  • cx_Freeze 5.0 for Python 3.5 on Windows 글에 있는 대로 cx_Freeze source code로 부터 wheel을 만들어 pip로 설치하는 방법
  • cx_Freeze 5.0 for Python 3.5 on Windows 글이 있는 github에서 제공하는 wheel을 download받아 pip로 설치하는 방법

현재 기준 (2016.04.19)으로 cx_Freeze source code의 마지막 commit은 2016.03.29이고 wheel의 마지막 commit은 2016.04.09이라서 최종 source를 반영했다는 가정을 한다면 둘 중 편한 방법을 선택하면 된다.
이번 post에서는 간단하게 하기위해 wheel을 download받아 설치하였다.

  1. cx_Freeze 5.0 for Python 3.5 on Windows 글에서 wheel을 download 한다.
  2. 해당 폴더로 이동한 후 cx_Freeze를 설치한다.
    (현재 windows에 설치된 python이 32bit라서 cx_Freeze-5.0-cp35-cp35m-win32.whl파일을 사용하였다.
    python 64bit를 사용하고 있다면 cx_Freeze-5.0-cp35-cp35m-win_amd64.whl 파일을 사용하면 된다.)

    > pip install cx_Freeze-5.0-cp35-cp35m-win32.whl
    Processing c:\users\imac\downloads\cx_freeze-wheels-master\cx_freeze-wheels-master\cx_freeze-5.0-cp35-cp35m-win32.whl
    Installing collected packages: cx-Freeze
    Successfully installed cx-Freeze-5.0

  3. pip로 보면 5.0이 설치된 것을 확인할 수 있다.

    > pip list
    …중략…
    cx-Freeze (5.0)
    …후략…

 

카테고리:Python

Windows에서 wxPython-Phoenix 사용시 DLL load failed 오류가 발생하는 경우 해결 방법

4월 19, 2016 3개의 댓글

문제 발생 환경 정보

  • Windows 8.1 K
  • Python 3.5.1 (32bit)
  • wxPython-Phoenix 3.0.3.dev1964+f780b21 (32bit)

wxPython-Phoenix를 설치하고 sample source를 작성하여 실행했더니 다음과 같은 오류가 발생하였다.

C:\Users\someone\Project\Nuri\InvoiceApp>python main.py
Traceback (most recent call last):
File “main.py”, line 3, in <module>
import wx
File “C:\Users\someone\Python3_5_1\lib\site-packages\wx\__init__.py”, line 17, in
<module>
from wx.core import *
File “C:\Users\someone\Python3_5_1\lib\site-packages\wx\core.py”, line 6, in <mod
ule>
from ._core import *
ImportError: DLL load failed: 지정된 모듈을 찾을 수 없습니다.

지정된 모듈을 찾다 실패했다는 내용인데 debugger를 봐도 wx\core.py에서 오류가 발생했다는 message외에는 도움이 될만한 내용을 찾지 못했다.

혹시나해서 wxPython-Phoenix snapshot page에서 다른 version을 3,4개 정도 설치해봤지만 모두 동일한 결과만 나올뿐이었다.

구글링도중 단서가 될만한 단어를 발견했다.

MSVCP140.DLL

좀 더 찾아가 보니 wxPython-users group에서 Microsoft Visual C++ Redistributable package 최신 version을 설치했더니 해결되었다는 글을 발견하였다.

Microsoft download center에서 최신 version인 Visual Studio 2015용 Visual C++ 재배포 가능 패키지를 download하여 설치해보았다.
현재 python을 32bit를 사용중에 있으므로 재배포 file중 vc_redist.x86.exe만 먼저 설치하고 sample source를 실행해 보았더니 문제 없이 실행되었다.

만약 사용중인 python version이 다르다면 최신 Visual C++ download 지원 page를 참고하여 설치하면 된다.

추가적으로 python 3.5의 what’s new 문서를 보니 Windows 개선사항에 보면 Microsoft Visual C++ 14.0을 사용해 build했다는 언급이 있다.

카테고리:Python

Windows에서 wxPython Phoenix 설치하기

4월 18, 2016 1개의 댓글

Windows에서 pip가 기본 내장된 Python을 설치하였다면 기본적으로는 Mac OS X에서 wxPython Phoenix 설치하기와 동일하게 진행하면 된다.
pip는 Python 2.7.9이상 혹은 Python 3.4이상에서 기본으로 포함되어 있다.

그런데 문제가 발생했다.
Python download page에서 python-3.5.1.exe를 다운받아 설치한 후 pip를 이용해 wxPython Phoenix를 설치하던 중 다음과 같은 error message를 만났다.

…전략…
Running command: build_wx
Command ‘”c:\users\someone\python3_5_1\python.exe” -c “import distutils.msvc9compiler as msvc; mc = msvc.MSVCCompiler(); mc.initialize(); print(mc.cc)”‘ failed with exit code 1.
Trackback (most recent call last):
File “<String>”, line 1, in <Module>
File “c:\users\someone\python3_5_1\lib\distutils\msvc9compiler.py”, line 374,in initialize
vc_env = query_vcvarsall(VERSION, plat_spec)
…중략…
You are using pip version 7.1.2, however version 8.1.1 is available.
You should consider upgrading via the `python -m pip install --upgrade pip` command.

역시나 친절한 error message다. 시키는 대로 pip를 upgrade하였다.

python -m pip install --upgrade pip

Successfully installed pip-8.1.1이라는 message가 뜬 후 다시 Phoenix를 설치해 보았다.

pip install --upgrade --trusted-host wxpyt
hon.org --pre -f http://wxpython.org/Phoenix/snapshot-builds/ wxPython_Phoenix

역시나 다음과 같은 message를 보여주며 설치 완료되었다.

Collecting wxPython-Phoenix
Downloading http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3
.dev1964+f780b21-cp35-cp35m-win32.whl (11.3MB)
100% |################################| 11.3MB 3.3MB/s
Installing collected packages: wxPython-Phoenix
Successfully installed wxPython-Phoenix-3.0.3.dev1964+f780b21

카테고리:Python

Mac OS X에서 wxPython Phoenix 설치하기

4월 11, 2016 1개의 댓글

현재(2016-04-11)까지는 wxPython-Phoenix는 snapshot build만 제공을 하고 있어
pip install wxpython과 같은 식으로 설치가 되진 않는다.

wxPython의 wiki페이지에 보면 다양한 설치방법이 있는데 이 중에서 pip를 사용하여 설치하는 방법을 공유하고자 한다.

pip install --upgrade --trusted-host wxpython.org --pre -f http://wxpython.org/Phoenix/snapshot-builds/ wxPython_Phoenix

다음과 같은 메시지가 출력되면서 설치가 된다.

Collecting wxPython-Phoenix
Downloading http://wxpython.org/Phoenix/snapshot-builds/wxPython_Phoenix-3.0.3.dev1964+f780b21-cp35-cp35m-macosx_10_6_intel.whl (29.7MB)
100% |████████████████████████████████| 29.7MB 3.1MB/s
Installing collected packages: wxPython-Phoenix
Successfully installed wxPython-Phoenix-3.0.3.dev1964+f780b21

그런데 설치가 완료되어 간단하게 빈 window를 띄우는 sample을 작성하여 실행해보니 다음과 같은 메시지가 출력되며 실행되지 않았다.

This program needs access to the screen.
Please run with a Framework build of python, and only when you are logged in on the main display of your Mac.

구글링을 해서 찾아보니 다양한 해결 방안을 제시하고 있었지만 가장 간단한 방법으로 해결하였다.

env PYTHON_CONFIGURE_OPTS=”--enable-framework” pyenv install 3.5.1

python 3.5.1을  –enable-framework option을 주어 재설치하게되니 window가 정상적으로 실행되었다.

카테고리:Python