简体   繁体   English

为什么exec(“break”)不在while循环中工作

[英]Why doesn't exec(“break”) work inside a while loop

As the question asks, why doesn't the below code work: 正如问题所问,为什么以下代码不起作用:

while True:
      exec("break")

I am executing the above in pycharm via python 3.5.2 console. 我通过python 3.5.2控制台在pycharm中执行上面的操作。 I initially thought it was a context issue but after reading the documentation, I haven't come closer to understanding why this error ocurs. 我最初认为这是一个上下文问题,但在阅读文档之后,我还没有接近理解为什么会发生这种错误。

SyntaxError: 'break' outside loop

Thanks in advance :) 提前致谢 :)

EDIT: I understand that it works without exec() by the way, I'm curious why it won't work with exec (as my circumstances required it) - comprehensive answers welcome. 编辑:我知道它的工作没有exec()顺便说一句,我很好奇为什么它不能与exec一起工作(因为我的情况需要它) - 全面的答案欢迎。

This is because exec() is ignorant to your surrounding while loop. 这是因为exec()对你周围的循环无知。 So the only statement that exec() sees in your example is break . 因此, exec()在您的示例中看到的唯一语句是break Instead of using exec("break") , simply use break as is. 而不是使用exec("break") ,只需使用break

The only access the exec() function has to its surrounding scope, is the globals() and locals() dictionaries. exec()函数对其周围范围的唯一访问是globals()locals()字典。 The documentation for exec() provides some insight into how exec() works: exec()的文档提供了一些有关exec()如何工作的见解:

This function supports dynamic execution of Python code. 此函数支持Python代码的动态执行。 object must be either a string or a code object. object必须是字符串或代码对象。 If it is a string, the string is parsed as a suite of Python statements which is then executed (unless a syntax error occurs). 如果它是一个字符串,则将该字符串解析为一组Python语句,然后执行该语句(除非发生语法错误)。 [1] If it is a code object, it is simply executed. [1]如果是代码对象,则只执行它。 In all cases, the code that's executed is expected to be valid as file input (see the section “File input” in the Reference Manual). 在所有情况下,执行的代码应该作为文件输入有效(请参见“参考手册”中的“文件输入”部分)。 Be aware that the return and yield statements may not be used outside of function definitions even within the context of code passed to the exec() function. 请注意,即使在传递给exec()函数的代码的上下文中,也不能在函数定义之外使用return和yield语句。 The return value is None. 返回值为None。

In all cases, if the optional parts are omitted, the code is executed in the current scope. 在所有情况下,如果省略可选部分,则代码在当前范围内执行。 If only globals is provided, it must be a dictionary, which will be used for both the global and the local variables. 如果只提供全局变量,则它必须是字典,它将用于全局变量和局部变量。 If globals and locals are given, they are used for the global and local variables, respectively. 如果给出全局变量和局部变量,则它们分别用于全局变量和局部变量。 If provided, locals can be any mapping object. 如果提供,则locals可以是任何映射对象。 Remember that at module level, globals and locals are the same dictionary. 请记住,在模块级别,全局变量和本地变量是相同的字典。 If exec gets two separate objects as globals and locals, the code will be executed as if it were embedded in a class definition. 如果exec获得两个单独的对象作为全局变量和局部变量,则代码将被执行,就像它嵌入在类定义中一样。

If the globals dictionary does not contain a value for the key builtins , a reference to the dictionary of the built-in module builtins is inserted under that key. 如果全局字典不包含键内置函数的值,则在该键下插入对内置模块内置字典的引用。 That way you can control what builtins are available to the executed code by inserting your own builtins dictionary into globals before passing it to exec(). 这样,通过将自己的内置字典插入到globals中,然后将其传递给exec(),就可以控制执行代码可用的内置函数。

The exec statement runs a bit of code independently from the rest of your code. exec语句独立于代码的其余部分运行一些代码。

Hence, the line: 因此,该行:

exec("break")

is tantamount to calling break out of nowhere, in a script where nothing else happens, and where no loop exists. 等于在一个没有其他任何事情的脚本中调用break冒出的地方,并且没有循环存在。

The right way to call the break statement is: 调用break语句的正确方法是:

while True:
    break

EDIT 编辑

The comment from Leaf made me think about it. Leaf的评论让我思考它。

Actually, the exec statement does not run the code out of nowhere. 实际上, exec语句不会无处运行代码。

>>> i = 12
>>> exec("print(i)")
12

A better answer, as far as I understand, is that exec runs a piece of code in the same environment as the original code, but independently from it. 据我所知,一个更好的答案是exec在与原始代码相同的环境中运行一段代码,但独立于它。

This basically means that all the variables that exist at the moment exec is called can be used in the code called by exec . 这基本上意味着,所有存在此刻的变量exec被称为可以通过调用的代码中使用exec But the context is all new, so return , break , continue and other statements that need a context, will not work, unless the right context is created. 但是上下文都是新的,所以returnbreakcontinue和其他需要上下文的语句都不会起作用,除非创建了正确的上下文。

By the way, I kept the word "statement" when talking about exec , but it has become a function in Python3, the same way print did. 顺便说一下,在谈论exec时我保留了“声明”这个词,但它已经成为Python3中的一个函数,就像print一样。

exec() is a function. exec()是一个函数。 Assuming for simplicity that a function call constitutes a statement of its own (just like in your example), it may end in one of the following ways: 假设为简单起见,函数调用构成了自​​己的语句(就像在您的示例中一样),它可能以下列方式之一结束:

  1. the function returns normally - in this case the next statement according to the control flow is executed; 函数正常返回 - 在这种情况下,执行根据控制流的下一个语句;

  2. an exception is raised/thrown from the function - in this case the matching except clause on the call stack (if any) is executed 从函数引发/抛出异常 - 在这种情况下,执行调用堆栈上的匹配except子句(如果有)

  3. the entire program is terminated due to an explicit call to exit() or equivalent - there is nothing to execute. 由于显式调用exit()或等效函数,整个程序终止 - 没有任何东西可以执行。

Calling a break (as well as return or yield ) from inside exec() would modify the program execution flow in a way that is incompatible with the described aspect of the function call semantics. exec()内部调用break (以及returnyield )将以与函数调用语义的描述方面不兼容的方式修改程序执行流。

Note that the documentation on exec() contains a special note on the use of return and yield inside exec() : 请注意, 在文件exec()包含对使用的特殊说明, returnyield内部exec()

Be aware that the return and yield statements may not be used outside of function definitions even within the context of code passed to the exec() function. 请注意,即使在传递给exec()函数的代码的上下文中,也不能在函数定义之外使用returnyield语句。

A similar restriction applies to the break statement (with the difference that it may not be used outside loops ), and I wonder why it was not included in the documentation. 类似的限制适用于break语句(区别在于它可能不在循环外使用),我想知道为什么它没有包含在文档中。

exec is a built in function , exec是内置函数,

Python insists that break should happen inside the loop,not inside a function Python坚持认为break应该在循环内部发生,而不是在function内部发生

What is happening in your code is you are putting break inside a function which is exec you can't break out of a loop by executing a break within a function that's called inside the loop. 什么在你的代码的情况是你把break一个内部functionexec你无法通过执行跳出循环的break一这就是所谓的内循环功能内。

For Ex 对于Ex

>>> def func():
        break
SyntaxError: 'break' outside loop
>>> 

Try break without exec(): 尝试在没有exec()的情况下休息:

while True:
  break

exec function runs code inside a code and that means it runs out of nowhere! exec函数在代码中运行代码,这意味着它无处不在! So, your while loop doesn't catch it. 所以,你的while循环没有抓住它。 Your file is <stdin> . 您的文件是<stdin> exec runs on another file called <string> . exec在另一个名为<string>文件上运行。 it doesn't recognize it where are you trying to break a loop where there is not a loop. 它无法识别它在哪里试图打破没有循环的循环。 So, your code is this: 所以,你的代码是这样的:

while True:
    exec("break")

It should be like this: 它应该是这样的:

while True:
    break

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM