2016-04-25 15 views
1

は2つのバージョン番号と比較指定子を与えられました。Pythonの動的な比較指定子でバージョン番号を比較

私を、私はそうのようdistutils.versionからLooseVersionを使用してバージョンを比較できることを発見しました:

LooseVersion("1.2.3") >= LooseVersion("2.0.0") 

をしかし、どのように、私は比較自体がspecifierに渡さに依存することができますか?

私はhereからソリューションを使用することができます。

def check_versions(ver1, specifier, ver2): 
    return { 
     '==': LooseVersion(ver1) == LooseVersion(ver2), 
     '>=': LooseVersion(ver1) >= LooseVersion(ver2), 
     '<=': LooseVersion(ver1) <= LooseVersion(ver2), 
     '>': LooseVersion(ver1) > LooseVersion(ver2), 
     '<': LooseVersion(ver1) < LooseVersion(ver2), 
    }.get(x, False) 

しかし、それはちょうど私には本当に不格好な感じ。より洗練されたソリューションはありませんか?

+0

なぜセミバーを使用しないのですか?https://github.com/k-bx/python-semver –

+0

@Apero比較演算子が動的な場合は、チェックが< 'または' == 'か何か他の場合、' semver'はどのように役立ちますか? –

+0

ああ私はその重要なポイントを逃した、確かに –

答えて

5

可能なすべてのバージョンの比較を使って辞書を作成するには、使用されている演算子のルックアップを作成するだけです(例:

0123)。
import operator as op 
from distutils.version import LooseVersion 

lookup = {'<': op.lt, '<=': op.le, '==': op.eq, '>=': op.ge, '>': op.gt} 

def check_versions(ver1, specifier, ver2): 
    try: 
     return lookup[specifier](LooseVersion(ver1), LooseVersion(ver2)) 
    except KeyError: 
     # unknown specifier 
     return False 
1

evalを使用できます。 specifierは、ユーザー入力から来る場合

def check_versions(ver1, specifier, ver2): 
    return eval("LooseVersion(ver1) " + specifier + " LooseVersion(ver2)") 

は、しかし、注意してください、あなたは悪意のあるコール得ることができる:、

check_versions("1.0.0", " == 1; pkg_resources.get_distribution("really bad virus"); 
       import really_bad_virus; really_bad_virus.bobby_tables();", "1.0.0") 

その場合は、あなたsanitize your inputsでしそれらを評価する前に:代わりに

def check_versions(ver1, specifier, ver2): 
    if specifier in ['==', '<=', '>=', '>', '>']: 
     return eval("LooseVersion(ver1) " + specifier + " LooseVersion(ver2)") 
+3

私は言うべきです、これは 'eval'をもたらす価値のあるものではありません。誰かがこれを見るたびに、彼らはそれが安全かどうかを止めて考える必要があります。 5行を節約する価値はありません。 (また、あなたのリストにはない 'specifier 'の扱いはありません。) – user2357112