[英]Why is my local variable being accessed like it's a global variable?
我有这段代码,它以某种方式将config
视为全局变量,即使它是局部变量。 我的同事刚刚注意到这一点,因为他们正在将脚本变成 Lambda function 并且 AWS 不断给他们一个NameError
:
错误消息: name 'config' is not defined
如果我在终端中运行以下命令,它就可以正常工作。 问题是,由于get_fields_for_issuetype
function 中未定义config
,因此是否应该出错,还是我遗漏了什么? 为什么它工作得很好?
Lambda 代码和这个代码之间的唯一区别是 Lambda 代码有一个constants.py
,其中定义了ProjectConfig
和project_configs
,然后导入到主代码中。
这是在我的终端中运行良好的代码:
import requests
from collections import namedtuple
BASE_URL = "https://example.com"
ProjectConfig = namedtuple("ProjectConfig", "projects required_fields tab_name")
project_configs = [
ProjectConfig(
projects=sorted(
[
"AGNT",
"APS",
"CLOD",
]
),
required_fields=[
"Field 1",
"Field 2",
],
tab_name="Group_1_Fields",
),
ProjectConfig(
projects=sorted(
[
"ABAGNT",
"ABAPS",
"ABCLOD",
]
),
required_fields=[
"Field 3",
"Field 4",
],
tab_name="Group_2_Fields",
),
]
def auth():
email = "email@email.com"
pwd = "***"
credentials = (email, pwd)
session = requests.Session()
session.auth = credentials
return session
def get_fields_for_issuetype(project_key, session):
url = (BASE_URL + f"/something/something")
response = session.get(url)
data = response.json()
project = data["projects"][0]
proj_key = project["key"]
name = project["name"] + f" ({proj_key}) - Issue Types"
issuetypes = project["issuetypes"]
for issuetype in issuetypes:
issuetype_name = issuetype["name"]
required_fields = config.required_fields.copy()
def main(config):
session = auth()
for project in config.projects:
table = get_fields_for_issuetype(project, session)
if __name__ == "__main__":
for config in project_configs:
main(config)
这是变成 Lambda function 时不运行的代码:
app.py
import requests
from constants import API_TOKEN, BASE_URL, USER_NAME, project_configs
def auth():
email = USERNAME
pwd = API_TOKEN
credentials = (email, pwd)
session = requests.Session()
session.auth = credentials
return session
def get_fields_for_issuetype(project_key, session):
url = (BASE_URL + f"/something/something")
response = session.get(url)
data = response.json()
project = data["projects"][0]
proj_key = project["key"]
name = project["name"] + f" ({proj_key}) - Issue Types"
issuetypes = project["issuetypes"]
for issuetype in issuetypes:
issuetype_name = issuetype["name"]
required_fields = config.required_fields.copy()
def main(config):
session = auth()
for project in config.projects:
table = get_fields_for_issuetype(project, session)
def lambda_handler(event, context):
for config in project_configs:
main(config)
constants.py
:
from collections import namedtuple
BASE_URL = "https://example.com"
ProjectConfig = namedtuple("ProjectConfig", "projects required_fields tab_name")
project_configs = [
ProjectConfig(
projects=sorted(
[
"AGNT",
"APS",
"CLOD",
]
),
required_fields=[
"Field 1",
"Field 2",
],
tab_name="Group_1_Fields",
),
ProjectConfig(
projects=sorted(
[
"ABAGNT",
"ABAPS",
"ABCLOD",
]
),
required_fields=[
"Field 3",
"Field 4",
],
tab_name="Group_2_Fields",
),
]
这个 function 在 scope 中没有config
:
def get_fields_for_issuetype(project_key, session):
url = (BASE_URL + f"/something/something")
...
for issuetype in issuetypes:
issuetype_name = issuetype["name"]
required_fields = config.required_fields.copy()
在您的本地代码中,您有以下内容:
if __name__ == "__main__":
for config in project_configs:
main(config)
这会将config
放入上述 function 可以访问的 scope 中,因为它位于get_fields_for_issuetype()
定义之外并且位于同一文件中。 您需要传递config
才能在 Lambda function 中按预期工作。
您可以通过像这样定义 function 来了解其工作原理:
def f():
def g():
print(f"I have access to {x=}")
x = "an outer scope variable"
g()
Even though x
is defined after the function g()
, g()
has access to it because the scope of x
is visible to g()
- they both are in the scope of function f()
. 同样,当您使用原始文件时,您可以将其视为正在运行的不可见f()
。 事实上, if __name__ = "__main__"
基本上表明你在一个名为__main__
的 function 中。 get_fields_for_issuetype
可以看到 function 因为这是定义它的地方。
if __name__ == "__main__":
for config in project_configs:
main(config)
这个就在底部。 这在全局 scope 处声明了一个名为config
的变量。 for
不会创建自己的 scope,所以这仍然是全局范围的。 当您在本地不存在这样的名称的 function 中使用config
时,它将继承全局名称。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.