Python exec

[ 参照リンク:Pythonの名前空間とスコープ](https://www.imangodoc.com/106.html)

目次

exec()は簡単に使用できます

単純な文字列コードを動的に実行する

より複雑なコードを動的に実行する

ファイル内のPythonコードを実行します

execでパラメータを渡す

使用中に発生した問題

参照

exec()は簡単に使用できます

個人的には、Pythonでexec()を使用して、文字列コードを動的に実行することを好みます。forループでは、list1 = 1、list2 = 2、list3 = 3 ...などの多数のステートメントをすばやく実行して、コードを表示できます。より簡潔に。

まず、exec()について簡単に説明します。exec()は非常に興味深く実用的な組み込み関数です。数式の結果を計算する機能しか実行できないeval()とは異なり、exec()は複雑なPythonを動的に実行できます。コードは強力ですが、踏みやすい小さな場所がたくさんあります。ピットは良いですが、理解しにくいです。光と影が共存しています。

単純な文字列コードを動的に実行する

より複雑なコードを動的に実行する

func = "def fact(n):\n\treturn 1 if n==1 else n*fact(n-1)"

exec(func)

a = fact(5)

print(a)

ファイル内のPythonコードを実行します

eg.txtに入れたいPythonコードを保存します

def fact(n):

if n==1:

return 1

else:

return n*fact(n-1)

t = fact(6)

print(t)

execでパラメータを渡す

x = 10

expr = """

z = 30

sum = x + y + z

print(sum)

"""

def func():

y = 20

exec(expr)

exec(expr, {'x': 1, 'y': 2})

exec(expr, {'x': 1, 'y': 2}, {'y': 3, 'z': 4})

func()

使用中に発生した問題

今日それを使用しているときにいくつかの問題に遭遇し、単にそれを記録します。

def main():

file_list = [2014, 2045, 2065, 2070, 2080, 2110, 2123, 2133]

generate_outliers_analysis_log(file_list, "log/outliers.log")

for file in file_list:

csv_df = csv_file_to_df(r"D:/FTPD/newEnv/" + str(file) + ".csv")

port_suffix = [33, 35, 36, 37, 39, 40]

loc = locals()

for suffix in port_suffix:

#文字列コードを実行して、同じステートメントを繰り返し実行しないようにします

exec("sorted_df_%s =  get_sorted_port_df(csv_df, '25GE1/0/%s')" % (str(suffix), str(suffix)))

sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]

sorted_df_37, sorted_df_39, sorted_df_40 = loc["sorted_df_37"], loc["sorted_df_39"], loc["sorted_df_40"]

sorted_df_list = [sorted_df_33, sorted_df_35, sorted_df_36, sorted_df_37, sorted_df_39, sorted_df_40]

name_list = ["25GE1/0/33", "25GE1/0/35", "25GE1/0/36", "25GE1/0/37", "25GE1/0/39", "25GE1/0/40"]

save_port_figure_and_excel(range(1, 7), sorted_df_list, name_list, str(file), 'port_csv/' + str(file) + '.xlsx')

次のコード行は、実行中にエラーが発生しました。

sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]

エラーメッセージは次のとおりです。

sorted_df_33, sorted_df_35, sorted_df_36 = loc["sorted_df_33"], loc["sorted_df_35"], loc["sorted_df_36"]KeyError: 'sorted_df_33'。

一見奇妙です。KeyErrorの問題を回避するために、execはlocals()と組み合わせて使用されることがよくあります。

まず、地元の人に関しては、注目に値する4つのポイントがあると思います。

  1. locals()ディクショナリは、ローカルネームスペースのプロキシであり、ローカルスコープの変数を収集します。コードの実行中にローカル変数が動的に変更された場合、ディクショナリのみが影響を受け、実際のローカルスコープ変数は影響を受けません。 2. locals()が再度呼び出されると(つまり、locals()が2回呼び出されると)、動的に変更されたコンテンツ(exec())は再収集のために破棄され、locals()は更新されて前のexec()が含まれなくなります。 )実行後のkvペアの辞書。 3.実行時のローカルネームスペースは変更できません。つまり、exec()関数での変数の割り当ては影響しませんが、locals()ディクショナリは可変であり、exec()関数の影響を受けます。 4. locals()ディクショナリはローカルネームスペース(dictionary)のプロキシであるため、現在のローカルスコープ内のすべてのローカル変数が含まれます。したがって、locals()の結果が変数に割り当てられると、循環参照が生成されます。 。

ポイント4の意味、簡単な例を挙げてください

def test():

a = 13

loc = locals()

exec('b = a + 1')

b = loc['b']

print(b)

上記の小さなコードでは、行loc = locals()が実行されると、locディクショナリには「loc」のキーがあります。これは、locディクショナリ自体のキーと値のペアです。

そして、このlocは循環参照です。以下のデバッグ図を見てください。 locals()には、現在のローカルスコープ内のすべてのローカル変数が含まれるためです。 loc自体もローカル変数であるため、循環参照を作成します。

幹部の一般的な落とし穴

https://segmentfault.com/a/1190000019217209

発生した問題の分析

上記のリンク先の記事を読んだ後、私は個人的に説明が非常に徹底的であると感じています。簡単に振り返ってみましょう。つまり、次の例1では、KeyErrorが報告され、次の例2では、エラーは報告されません。これは、locals()の呼び出し場所に関連しています。Locals()は、ローカル変数のディクショナリのコピーです。実行時のローカルネームスペース(ローカル変数ディクショナリ)は変更できないため、exec()関数での変数の割り当ては正しくありません。影響はありますが、locals()ディクショナリは可変であり、exec()関数の影響を受けます。つまり、後でexecで動的に実行される値を取得して新しい変数に割り当てる場合は、execの前にlocals()を呼び出す必要があります。そうしないと、取得できません。

さて、これに基づいて、今日発生した問題を確認しましょう。まず、上記の問題があるビジネスコードを簡略化して、以下の例3のexec + locals + placeholder example3を使用し、次にexample4のメソッドを使用して単純にします。検証。ねえ、ここに興味深い問題があります。論理的に言えば、example3()関数では、2行目がlocを定義します。ここのlocは、3行目と4行目の実行が完了した後にexecによって変更されます。 locには、「a0」、「a1」、「a2」、「a3」、「a4」の5つのキーが必要です。これはexample4でも確認されています。つまり、元の変数名を使用しない限り取得できます。このようなエラーが発生する理由がよくわかりません。これは、execとプレースホルダーの設計上の問題である可能性があります。これから、結論を導き出すこともできます。コードで動的に実行されるexecの変数値を取得するには、再実行しないことをお勧めします。名前を付けて、これらの小さくて些細な問題を見つけないようにして、より多くの時間を費やしてください。 :

参照

https://segmentfault.com/a/1190000014581721

https://segmentfault.com/a/1190000019217209

https://python3-cookbook.readthedocs.io/zh_CN/latest/c09/p23_executing_code_with_local_side_effects.html

Recommended Posts

Python exec
Pythonマルチスレッド
Python CookBook
Python FAQ
Python3辞書
Python3モジュール
python(you-get)
Python文字列
Python記述子
Pythonの基本2
Pythonノート
Python3タプル
CentOS + Python3.6 +
Python Advanced(1)
Pythonデコレータ
Python IO
Pythonマルチスレッド
Pythonツールチェーン
Python3リスト
Pythonマルチタスク-日常
Pythonの概要
pythonの紹介
Pythonアナリティック
Pythonの基本
07.Python3関数
Pythonの基本3
Pythonマルチタスクスレッド
Python関数
python sys.stdout
python演算子
Pythonエントリ-3
Centos 7.5 python3.6
Python文字列
pythonキューキュー
Pythonの基本4
Pythonの基本5
Centos6はPython2.7.13をインストールします
Pythonは質問に答えます
Pythonの基本構文(1)
Pythonはloopメソッドを終了します
Ubuntu16アップグレードPython3
Centos7はPython3.6をインストールします。
ubuntu18.04インストールpython2
Pythonの古典的なアルゴリズム
ubuntuを再学習します--python3
Python2.7 [インストールチュートリアル]
Python文字列操作
Python 3.9が登場!
Python研究ノート(1)
python学習ルート
CentOS7アップグレードpython3
Pythonレビュー1
linux + ubuntuはpythonを解決します
pythonの関数
Python学習変数タイプ
CentOSはPython3.6をインストールします
Python3.9の7つの機能
ubuntu12.04インストールpython3
Python-centos6のインストール
Centos7はPython2.7をインストールします
01.Pythonの概要