You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask中执行含函数的Python字符串报错NameError求助

问题:Flask类方法中exec定义函数后调用报NameError

我有一段用exec执行Python函数定义字符串的代码,在普通Python脚本(python3 test.py)里能正常运行:

# 包含函数定义的字符串
function_string = "def greet(name):\n    print('Hello, ' + name + '!')"

# 执行字符串代码
exec(function_string)

# 调用函数
name = "Alice"
greet(name)  # 输出:Hello, Alice!

但把这段代码放到Flask应用的类方法extract_all_delimiters里时,运行报错:

def extract_all_delimiters(self, processed_files_meta_data, set_delimiter_algorithm_fn: str):
    print(f'extract_all_delimiters()')
    delimiters = []
    exec(set_delimiter_algorithm_fn)
    # 测试用的函数定义字符串
    function_string = "def greet(name):\n    print('Hello, ' + name + '!')"

    # 执行字符串代码
    exec(function_string)

    # 尝试调用函数
    name = "Alice"
    greet(name)  # 这里报错:NameError: name 'greet' is not defined

控制台报错信息:

docwise-backend-web-1     | extract_all_delimiters()
docwise-backend-web-1     | 192.168.65.1 - - [15/Oct/2023 17:22:27] "POST /api/conversation/create_conversation HTTP/1.1" 500 -
docwise-backend-web-1     | Traceback (most recent call last):
docwise-backend-web-1     |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 2548, in __call__
docwise-backend-web-1     |     return self.wsgi_app(environ, start_response)
docwise-backend-web-1     |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 2528, in wsgi_app
docwise-backend-web-1     |     response = self.handle_exception(e)
docwise-backend-web-1     |                ^^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/usr/local/lib/python3.11/site-packages/flask_cors/extension.py", line 176, in wrapped_function
docwise-backend-web-1     |     return cors_after_request(app.make_response(f(*args, **kwargs)))
docwise-backend-web-1     |                                                 ^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 2525, in wsgi_app
docwise-backend-web-1     |     response = self.full_dispatch_request()
docwise-backend-web-1     |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 1822, in full_dispatch_request
docwise-backend-web-1     |     rv = self.handle_user_exception(e)
docwise-backend-web-1     |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/usr/local/lib/python3.11/site-packages/flask_cors/extension.py", line 176, in wrapped_function
docwise-backend-web-1     |     return cors_after_request(app.make_response(f(*args, **kwargs)))
docwise-backend-web-1     |                                                 ^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 1820, in full_dispatch_request
docwise-backend-web-1     |     rv = self.dispatch_request()
docwise-backend-web-1     |          ^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/usr/local/lib/python3.11/site-packages/flask/app.py", line 1796, in dispatch_request
docwise-backend-web-1     |     return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
docwise-backend-web-1     |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/app/routes/conversation.py", line 11, in create_conversation_route
docwise-backend-web-1     |     return create_conversation_controller()
docwise-backend-web-1     |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/app/controllers/conversation/create_conversation_controller.py", line 160, in create_conversation_controller
docwise-backend-web-1     |     files_chuncks:List[object] = chunck_text(delimiter_algorithm,files,user_id)
docwise-backend-web-1     |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/app/controllers/conversation/create_conversation_controller.py", line 111, in chunck_text
docwise-backend-web-1     |     extracted_delimiters = delimiter_chuncker.extract_all_delimiters(processed_files_meta_data,delimiter_algorithm['algorithm'])
docwise-backend-web-1     |                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
docwise-backend-web-1     |   File "/app/util/text_chunckers/delimiter.py", line 102, in extract_all_delimiters
docwise-backend-web-1     |     greet(name)  # This will print: Hello, Alice!
docwise-backend-web-1     | NameError: name 'greet' is not defined

原因分析

这是Python中exec函数在类方法局部作用域下的特性导致的:

  • 在普通脚本的全局作用域中,exec默认会把定义的函数直接存入全局命名空间,所以后续能直接调用。
  • 但在类方法的局部作用域里,Python的函数局部命名空间是在编译阶段就确定的,exec默认使用的局部作用域对象(通过locals()获取)是只读的,修改后不会同步到当前局部命名空间。这意味着用exec定义的函数不会自动出现在当前方法的局部变量中,自然就找不到greet这个名字。

解决方法

有两种可靠的方式解决这个问题:

方法1:显式指定全局命名空间

把exec的执行结果存入全局命名空间,后续从全局空间调用函数:

def extract_all_delimiters(self, processed_files_meta_data, set_delimiter_algorithm_fn: str):
    print(f'extract_all_delimiters()')
    delimiters = []
    exec(set_delimiter_algorithm_fn, globals())
    function_string = "def greet(name):\n    print('Hello, ' + name + '!')"

    # 指定globals()作为exec的命名空间
    exec(function_string, globals())

    name = "Alice"
    greet(name)  # 现在可以正常调用

方法2:使用自定义字典作为命名空间

创建一个自定义字典来存储exec执行后的变量,后续从字典中取出函数调用:

def extract_all_delimiters(self, processed_files_meta_data, set_delimiter_algorithm_fn: str):
    print(f'extract_all_delimiters()')
    delimiters = []
    # 自定义命名空间字典
    exec_namespace = {}
    exec(set_delimiter_algorithm_fn, exec_namespace)
    function_string = "def greet(name):\n    print('Hello, ' + name + '!')"

    # 把执行结果存入自定义字典
    exec(function_string, exec_namespace)

    name = "Alice"
    # 从字典中取出函数调用
    exec_namespace['greet'](name)

这种方式更安全,不会污染全局命名空间,适合在类方法或函数内部使用。


内容的提问来源于stack exchange,提问作者user17281101

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 08:41:11