2009-02-22 1 views

답변

16

나는 문자열을 구문 분석 것 : 보안 위험이기 때문에

>>> def convert(s): 
    try: 
     return float(s) 
    except ValueError: 
     num, denom = s.split('/') 
     return float(num)/float(denom) 
... 

>>> convert("0.1234") 
0.1234 

>>> convert("1/2") 
0.5 

일반적으로 사용하는 평가는 나쁜 생각입니다. 특히 평가되는 문자열이 시스템 외부에서 제공된 경우입니다.

+1

+1. eval은이 경우 완전히 불필요하며 (물론 나 이외의) 누군가가 옳은 것을 고수하게되어 기쁩니다. –

+0

동료가 악의적 인 사회 병리학자가 아닌 한 Eval은 보안 상 위험하지 않습니다. 이 경우에는 필요하지 않지만 오픈 소스 코드 자체보다는 보안 위험이 없습니다. –

+0

아주 좋습니다. 그 끈은 외부에서 온 것입니다. 그래서 나는 안전하게 가야합니다. 그리고 나쁜 습관을 배우지 않으려 고 노력해야합니다. 나는 그것을 분석 할 필요가 없기를 바랬지 만 이것은 너무 나쁘지 않고 매력처럼 작동합니다. – ketorin

3

/ 연산자는 정수 나눗셈을 수행

평가 내가 생각 없지만 운이 된 것입니다. 시도 : eval() 잠재적 위험

>>> eval("1.0*" + "1/2") 
0.5 

때문에, 당신은 항상 당신이 그것으로 전달하는 정확하게 무엇을 확인해야합니다 :

>>> import re 
>>> s = "1/2" 
>>> if re.match(r"\d+/\d+$", s): 
...  eval("1.0*" + s) 
... 
0.5 

을 그러나 정규식에 대해 입력을 일치의 문제로 이동하는 경우 먼저, 당신은뿐만 아니라 분할 자신을, 분자와 분모를 추출 r"(\d+)/(\d+)$"를 사용하고, 완전히 피할 수 eval() :

>>> m = re.match(r"(\d+)/(\d+)$", s) 
>>> if m: 
...  float(m.group(1))/float(m.group(2)) 
... 
0.5 
+0

감사, 평가 후면 힌트는 지금 좋은 내가 지적 안전한 솔루션을 필요로 나는 깨달았다 것을 제외하고 ... 단지 좋은 일을 할 것입니다 아웃. – ketorin

0

1과 2가 파이썬에 의해 정수로 해석되고 부동되지 않기 때문입니다. 그것은 1.0/2.0이거나 그 일부를 혼합해야합니다.

4

원하는 동작을 얻으려면 from __future__ import division을 사용하십시오. 그런 다음 핀치로 문자열에서 부유물 목록을 얻으려면

from __future__ import division 
strings = ["0.1234", "1/2", "2/3"] 
numbers = map(eval, strings) 

과 같이 할 수 있습니다. 이것을 "올바른"방법으로 사용하려면 eval()을 사용하지 말고 대신 문자열을 허용하는 함수를 작성하고 슬래시가 포함되어 있지 않으면 float()을 호출하거나 문자열을 구문 분석하고 분자와 분모를 나누십시오 그 안에 슬래시. 그것을 할 수

한 가지 방법 :

def parse_float_string(x) 
    parts = x.split('/', 1) 
    if len(parts) == 1: 
     return float(x) 
    elif len(parts) == 2: 
     return float(parts[0])/float(parts[1]) 
    else: 
     raise ValueError 

가 그럼 그냥 map(parse_float_string, strings)는 당신에게 당신의 목록을 얻을 것이다.

2

python에서와 마찬가지로 정수의 지수는 정수입니다. 그래서 몇 가지 선택이 있습니다.

from __future__ import division 

다른 하나는 유리수를 분할하는 것입니다 :

첫 번째는 단순히 정수 나누기 복귀 수레 만드는 것입니다

rat_str는 유리수와 문자열입니다
reduce(lambda x, y: x*y, map(int, rat_str.split("/")), 1) 

. 변환이 실패 할 경우

0

과 결합 된 from __future__ import division의 제안은 확실히 작동합니다.

그것은 아마 eval은 위험하므로 eval를 사용하는 것이 아니라 문자열을 구문 분석하지 않는 제안 그렇게 지적 가치 : 임의의 문자열이 eval로 전송하려면 몇 가지 방법이 있다면, 당신의 시스템은 취약하다 . 그래서 나쁜 습관입니다. (이것은 단지 신속하고 더러운 코드의 경우, 그것은 아마 그렇게 큰 거래이다!) 다른 사람들이 지적했듯이

7

, eval 잠재적 보안 위험, 확실히로 얻을 수있는 나쁜 습관이다 사용. 당신이 파이썬 2.6이있는 경우 문자열이 제공하는 ast.literal_eval를 사용할 수 있습니다,

그러나 : (__import__('os').system('rm -rf /') 당신이 exec만큼 위험한 생각하지 않는 경우, 같은 eval 보내고 뭔가를 상상) :

은 문자열, 숫자, 튜플, 목록, dicts, 부울 및 없음으로 만 구성 될 수 있습니다.

따라서는

+0

그것에 대해 몰랐습니다 - 감사합니다! –

+0

심각하게 혼란에 빠진 동료가 없어도 예제처럼 악의적 인 것으로 평가할 수 있습니까? Eval은 셸에 대한 액세스가 보안 위험이 아닌 보안 위험이 아닙니다. –

+0

공정한 점 .. 신뢰할 수없는 입력을 처리하지 않으면 eval은 위험하지 않습니다. 나는이 글의 영향을받는다고 생각한다 : http://phpxmlrpc.sourceforge.net/#security - PHP 녀석들은 eval을 없애야한다는 것을 깨닫기 전에 그들의 문제를 두 번 풀려고했다. 그래서 ... –

6

또 다른 옵션 (또한에만 2.6 이상) :-) 매우 안전 할 것을 fractions 모듈한다.

>>> from fractions import Fraction 
>>> Fraction("0.1234") 
Fraction(617, 5000) 
>>> Fraction("1/2") 
Fraction(1, 2) 
>>> float(Fraction("0.1234")) 
0.1234 
>>> float(Fraction("1/2")) 
0.5 
1

파이썬 3에서는 이것이 작동합니다.

>>> x = ["0.1234", "1/2"] 
>>> [eval(i) for i in x] 
[0.1234, 0.5] 
+1

파이썬 3에서는'__future__ import division'을 디폴트로했습니다 ... 파이썬 3에서는 미래가되었습니다! – kquinn

1

sympy 것은 여기에 당신을 도울 수 있습니다

import sympy 

half = sympy.Rational('1/2') 
p1234 = sympy.Rational('0.1234') 
print '%f, %f" % (half, p1234) 
관련 문제