私がPythonで読んでいる本では、コードを使い続けています eval(input('blah'))
ドキュメントを読んで理解しましたが、それによってinput()
機能がどのように変わるかはまだわかりません。
それは何をするためのものか?誰かが説明できますか?
私がPythonで読んでいる本では、コードを使い続けています eval(input('blah'))
ドキュメントを読んで理解しましたが、それによってinput()
機能がどのように変わるかはまだわかりません。
それは何をするためのものか?誰かが説明できますか?
回答:
関数evalを使用すると、Pythonプログラム自体でPythonコードを実行できます。
evalの例(インタラクティブシェル):
>>> x = 1
>>> eval('x + 1')
2
>>> eval('x')
1
eval()
は、非常に動的なコードの実行にも使用できますが、使用する前に、セキュリティとパフォーマンスのリスクを十分に理解しておく必要があります。
eval
、またそれはそれはと何を行うことができますeval
。
eval
は、安全でないことを除いて、単一の式しか評価できないため、コードパッドのようにプログラム全体を実行することはできません。
eval()
文字列をコードとして解釈します。非常に多くの人々がこれを使用することについてあなたに警告した理由は、ユーザーがコンピュータ上でコードを実行するオプションとしてこれを使用できるためです。あなたが持っている場合eval(input())
やos
、インポート、人はに入力することができinput()
os.system('rm -R *')
、あなたのホームディレクトリ内のすべてのファイルを削除することになります。(あなたがUNIXシステムを持っていると仮定します)。使用eval()
はセキュリティホールです。文字列を他の形式に変換する必要がある場合は、そのようなことを行うようにしてくださいint()
。
eval
with input()
はセキュリティホールです。input()
evalステートメントの中に入れないでください。大丈夫です。
eval
、多くの場合、セキュリティの問題です。
input
通常のコンソールからデータを受け取り、ユーザは、単にプログラムを終了して入力することができrm -R *
...とにかく
ここには良い答えがたくさんありeval()
ますが、そのglobals
とlocals
kwargsのコンテキストでの使用については説明されていませんeval(expression, globals=None, locals=None)
(つまり、eval
こちらのドキュメントを参照)。
これらは、関数を介して使用できる関数を制限するために使用できますeval
。たとえば、あなたは通訳新鮮なのpythonをアップロードする場合locals()
とglobals()
、このように同じと見て何かになります:
>>>globals()
{'__loader__': <class '_frozen_importlib.BuiltinImporter'>, '__doc__': None,
'__spec__': None, '__builtins__': <module 'builtins' (built-in)>,
'__package__': None, '__name__': '__main__'}
builtins
モジュールには、システムに重大な損傷を与える可能性のある機能が確かにあります。しかし、利用可能にしたくないものはすべてブロックすることが可能です。例を見てみましょう。システムで使用可能なコアのドメインを表すリストを作成するとします。私には8つのコアがあるので、リストが必要です[1, 8]
。
>>>from os import cpu_count
>>>eval('[1, cpu_count()]')
[1, 8]
同様にすべて__builtins__
利用可能です。
>>>eval('abs(-1)')
1
OK。そこで、公開したい1つの関数と、公開したくない1つの(はるかに複雑になる可能性がある)メソッドの例を確認します。だからすべてをブロックしましょう。
>>>eval('[1, cpu_count()]', {'__builtins__':None}, {})
TypeError: 'NoneType' object is not subscriptable
すべての__builtins__
機能を効果的にブロックし、システムに一定レベルの保護をもたらしました。この時点で、公開したい関数を追加し始めることができます。
>>>from os import cpu_count
>>>exposed_methods = {'cpu_count': cpu_count}
>>>eval('cpu_count()', {'__builtins__':None}, exposed_methods)
8
>>>eval('abs(cpu_count())', {'__builtins__':None}, exposed_methods)
TypeError: 'NoneType' object is not subscriptable
これで、cpu_count
不要なものをすべてブロックしながら、関数を使用できるようになりました。私の意見では、これは非常に強力であり、一般的な実装ではなく、明らかに他の回答の範囲からです。このような使い方はたくさんありますが、正しく扱えば、個人的にeval
は安全に大いに活用できると思います。
NB
これらのkwargs
優れた点は、コードの省略形を使い始めることができることです。インポートしたテキストを実行するパイプラインの一部としてevalを使用するとします。テキストは正確なコードである必要はありません。テンプレートファイル形式に従っていても、好きなように実行できます。例えば:
>>>from os import cpu_count
>>>eval('[1,cores]', {'__builtins__': None}, {'cores': cpu_count()})
[1, 8]
Python 2.xはとinput(...)
同等ですがeval(raw_input(...))
、Python 3.xのraw_input
名前がに変更さinput
れました。混乱を招いたと思われます(おそらくinput
Python 2.xのドキュメントを参照していました)。さらに、eval(input(...))
Python 3.xでは問題なく動作しますがTypeError
、Python 2ではが発生します。
この場合eval
、から返された文字列をinput
式に変換して解釈するために使用されます。一般にこれは悪い習慣だと考えられています。
input
何raw_input
が行われたかを示しています。
行を読んでそれを解釈するという、誤解を招く例かもしれません。
試しeval(input())
て入力してください"1+1"
-これは印刷されるはず2
です。Evalは式を評価します。
eval()
渡された文字列をPython式として評価し、結果を返します。たとえばeval("1 + 1")
、式"1 + 1"
を解釈して実行し、結果を返します(2)。
混乱するかもしれない理由の1つは、引用したコードに一定レベルの間接参照が含まれているためです。内部関数呼び出し(入力)が最初に実行されるため、ユーザーには「何とか」のプロンプトが表示されます。それらが「1 + 1」(わかりやすくするために追加した引用符、プログラムの実行時に入力しないでください)で応答すると想像してみてください。入力関数はその文字列を返し、その文字列を解釈する外部関数(eval)に渡されます。結果(2)を返します。
evalの詳細については、こちらをご覧ください。
eval()
は、その名前が示すように、渡された引数を評価します。
raw_input()
現在input()
、Python 3.xバージョンです。したがって、の最も一般的な使用例は、Pythonの2.xバージョンで提供されていeval()
た機能をinput()
提供するための使用です。raw_inputはユーザーが入力したデータを文字列として返し、inputは入力されたデータの値を評価して返しました。
eval(input("bla bla"))
したがって、の機能を複製します input()
、2.x、つまりユーザーが入力したデータを評価します。
つまりeval()
、渡された引数を評価してeval('1 + 1')
2を返します。
の便利なアプリケーションの1つはeval()
、文字列からPython式を評価することです。たとえば、辞書のファイル文字列表現からロードします。
running_params = {"Greeting":"Hello "}
fout = open("params.dat",'w')
fout.write(repr(running_params))
fout.close()
変数として読み取って編集します。
fin = open("params.dat",'r')
diction=eval(fin.read())
diction["Greeting"]+="world"
fin.close()
print diction
出力:
{'Greeting': 'Hello world'}
eval
ますか?
私はこの質問に答えるのが遅いですが、誰も質問に明確な答えを出すようには見えません。
ユーザーが数値を入力するinput()
と、文字列が返されます。
>>> input('Enter a number: ')
Enter a number: 3
>>> '3'
>>> input('Enter a number: ')
Enter a number: 1+1
'1+1'
したがって、eval()
文字列である戻り値(または式)を評価し、整数/浮動小数点数を返します。
>>> eval(input('Enter a number: '))
Enter a number: 1+1
2
>>>
>>> eval(input('Enter a number: '))
Enter a number: 3.14
3.14
もちろん、これは悪い習慣です。int()
または、この場合のfloat()
代わりに使用する必要がありますeval()
。
>>> float(input('Enter a number: '))
Enter a number: 3.14
3.14
評価文字列を単純なリテラルに制限する場合のもう1つのオプションは、を使用することast.literal_eval()
です。いくつかの例:
import ast
# print(ast.literal_eval('')) # SyntaxError: unexpected EOF while parsing
# print(ast.literal_eval('a')) # ValueError: malformed node or string
# print(ast.literal_eval('import os')) # SyntaxError: invalid syntax
# print(ast.literal_eval('1+1')) # 2: but only works due to a quirk in parser
# print(ast.literal_eval('1*1')) # ValueError: malformed node or string
print(ast.literal_eval("{'a':1}")) # {'a':1}
ドキュメントから:
式ノードまたはPythonリテラルまたはコンテナー表示を含む文字列を安全に評価します。提供される文字列またはノードは、は、文字列、バイト、数値、タプル、リスト、辞書、セット、ブール、およびなしのPythonリテラル構造構成されます。
これは、自分で値を解析する必要なしに、信頼できないソースからのPython値を含む文字列を安全に評価するために使用できます。演算子やインデックスなど、複雑な式を任意に評価することはできません。
なぜそれがそれほど制限されているのかについては、メーリングリストから:
リテラルを含む演算子式を許可することは可能ですが、現在の実装よりもはるかに複雑です。単純な実装は安全ではありません。基本的に無制限にCPUとメモリの使用を誘発することができます( "9 ** 9 ** 9"または "[None] * 9 ** 9"を試してください)。
有用性に関しては、この関数は、repr()によって文字列化されたリテラル値とコンテナーを「読み戻す」のに役立ちます。これは、たとえば、JSONに似ているがより強力な形式でのシリアル化に使用できます。
ast.literal_eval
あなたの'1+1'
例とは逆に、は演算子をサポートしていません。それでも、リスト、数値、文字列などをサポートしているため、一般的なeval
ユースケースの代替として適しています。