当我需要返回值时,exec返回一个nonetype [英] exec returns a nonetype, when I need the return value

查看:68
本文介绍了当我需要返回值时,exec返回一个nonetype的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我早些时候问了一个问题,但遇到了第二个问题.

I asked a question earlier, but ran into a second problem.

我正在编写一个程序,该程序读取一个文本文件,并执行文件中的所有代码.这是上课的,我们必须使用exec()

I am writing a program that reads in a text file, and executes all code within the file. This is for class, and we have to use exec()

我在运行代码时遇到此错误,并且无数次搜索并没有导致我找到解决方案.

I get this error upon running the code, and countless searching has not led me to a solution.

Traceback (most recent call last):
  File "doxecute.py", line 28, in <module>
    replace_code(statements, contents)
  File "doxecute.py", line 17, in replace_code
    contents = contents.replace("{%" + statement + "%}", statement)
TypeError: Can't convert 'NoneType' object to str implicitly

代码为

import sys
import re



def sortecute(data): 
    funcs = re.findall(r'{%(.*?)%}',data,re.DOTALL)#find executable statements
    return funcs

def replace_code(statements, contents):
    for statement in statements:
        if not statement[5:].startswith("print("):
            exec(statement[5:]) #execute code after the (letter)
            contents = contents.replace("{%" + statement + "%}", "")
        else:
            statement = exec(statement[5:])#error is here
            contents = contents.replace("{%" + statement + "%}", statement)

    print(contents)

f = open(sys.argv[1],"r")
contents = f.read()
f.close()

statements = sortecute(contents) #get data from file
statements  = sorted(statements) #sorts by letter

replace_code(statements, contents)

这是我读的文件.

The number {% (c) print(x) %} is a random number between 1 and 6
inclusive. If we multiply it by 2, we get {% (d) print(2*x) %}.

What's interesting is that the statements may appear out of order in the
document. {% (a) import random %} Thus I might generate the random
number in a location in the document well after referencing it.
{% (b) x = random.randint(1,6) %}

我无法找到如何获取exec语句的值.有人可以向我解释如何以下面列出的方式正确使用此功能

I can not find out how to get the value of the statement for exec. Can someone explain to me how to use this properly in the way listed below

You will need to use the exec function in Python. To get the output back, you will need to redirect output to your own stream. Your program should accept a filename as a command-line argument to operate on [8]

推荐答案

exec将始终返回None.从文档:

exec( object [,globals [,locals]] )

此函数支持动态 执行Python程式码.对象必须是字符串或代码 目的.如果是字符串,则将字符串解析为Python套件 然后执行的语句(除非发生语法错误). [1] 如果它是代码对象,则只需执行即可.在所有情况下,代码 执行的文件应作为文件输入有效(请参阅本节 参考手册中的文件输入".请注意,returnyield语句甚至不能在函数定义之外使用 在传递给exec()函数的代码的上下文中. 退货 值是None .

exec(object[, globals[, locals]])

This function supports dynamic execution of Python code. object must be either a string or a code 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). [1] If it is a code object, it is simply executed. 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. The return value is None.

这是一个非常奇怪的请求.但是,您可以捕获这样的输出:

This is a rather strange request. But you can capture the output like this:

>>> s = """The number {% (c) print(x) %} is a random number between 1 and 6
... inclusive. If we multiply it by 2, we get {% (d) print(2*x) %}.
...
... What's interesting is that the statements may appear out of order in the
... document. {% (a) import random %} Thus I might generate the random
... number in a location in the document well after referencing it.
... {% (b) x = random.randint(1,6) %}"""
>>> import re
>>> stmts = re.findall(r'{%\s*\((\w*)\)\s*(.*)%}',s)
>>> stmts
[('c', 'print(x) '), ('d', 'print(2*x) '), ('a', 'import random '), ('b', 'x = random.randint(1,6) ')]

现在,您必须将输出重定向到某些流,以后可以对其进行操作:

Now, you have to redirect output to some stream which you can manipulate later:

>>> import io
>>> import sys
>>> stream = io.StringIO()
>>> stdout = sys.stdout # this keeps stdout so we can set it back
>>> sys.stdout = stream
>>> for _, statement in sorted(stmts):
...     exec(statement)
...
>>> sys.stdout = stdout # remember to reset stdout!

现在,您可以获得打印出的值:

And now, you can get the values that were printed:

>>> stream.getvalue()
'5\n10\n'
>>> stream.getvalue().split()
['5', '10']

尽管如此,我认为更简单的方法是将名称空间传递给dict:

Although, I think an easier way is to pass a namespace to the dict:

>>> namespace = {}
>>> for _, statement in sorted(stmts):
...     exec(statement, namespace)
...
5
10
>>> namespace.keys()
dict_keys(['__builtins__', 'random', 'x'])

除非您自己提供,否则命名空间将加载普通的__builtins__.因此,要获取在执行的代码中创建的每个名称,您可以找到namspace.keys dictview与包含字符串"__builtins__"

The namespace will get loaded with the normal __builtins__ unless you provide one yourself. So to get every name created in your executed code, you can find the difference between the namspace.keys dictview and a set contiaining the string "__builtins__"

>>> namespace.keys()
dict_keys(['__builtins__', 'random', 'x'])
>>> vals = namespace.keys() - {'__builtins__'}
>>> vals
{'random', 'x'}
>>> for val in vals:
...    print(namespace[val])
...
<module 'random' from '/Users/juan/anaconda3/lib/python3.5/random.py'>
5
>>>

尽管如此,如果您使用的是python 3.4> =,将stdout重定向到某些流要容易得多:

Although, if you are on python 3.4 >= it's a lot easier to redirect stdout to some stream:

>>> import contextlib
>>> stream = io.StringIO()
>>> with contextlib.redirect_stdout(stream):
...     for _, statement in stmts:
...         exec(statement)
...
>>> stream.getvalue()
'5\n10\n'
>>> stream.getvalue().split()
['5', '10']

这篇关于当我需要返回值时,exec返回一个nonetype的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆