[英]malformed node or string on line 1 when I use ast.literal_eval using discord.py
我尝试执行
import ast
ast.literal_eval('5+5')
然后我得到ValueError: malformed node or string on line 1: <ast.BinOp object at 0x70e6bd2830>
。
所以我尝试了另一个:
import ast
ast.literal_eval(str(5+5))
它成功地评估了它:
10
但是当我最终在实际命令$math 5+5
上使用它时
@client.command()
async def math(ctx, expression):
resp = ast.literal_eval(str(expression))
await ctx.send(resp)
我仍然收到相同的错误: ValueError: malformed node or string on line 1: <ast.BinOp object at 0x7d05357700>
出于某种原因。 我正在使用 Python 3.10.5。 我该如何解决这个问题? 任何帮助,将不胜感激。
整个代码:
import discord, ast
from discord.ext import commands
TOKEN = ""
client = commands.Bot(command_prefix="$")
prefix = client.command_prefix
def init():
client.run(TOKEN, reconnect=False)
@client.event
async def on_connect():
print('Connecting to server...')
@client.event
async def on_ready():
await client.change_presence(status=discord.Status.idle)
print('Logged in as ' + str(client.user))
print('Prefix: ' + str(prefix))
@client.command()
async def math(ctx, expression):
resp = ast.literal_eval(str(expression))
await ctx.send(resp)
init()
自 python 3.7 起,您不再允许在literal_eval
中进行加法。
我从这个答案中找到了一些可以使用的“安全表达式”。 这是一个简单的演示:
import ast
value = input()
co = ast.parse(value, mode='eval')
for node in ast.walk(co):
if not isinstance(node, (ast.Expression, ast.Constant, ast.Add, ast.Sub, ast.Mult, ast.Div, ast.Mod, ast.Pow, ast.BinOp, ast.USub, ast.UAdd, ast.UnaryOp)):
raise RuntimeError(f'Sorry! You gave an illegal syntax node: {node.__class__.__name__}')
print(eval(value))
这成功地评估了 python 中的有效数学,例如5 + 7*8 = 61
或5 ** 7 = 78125
,当然还有0.1 + 0.2 = 0.30000000000000004
。
不允许任何可能导致问题的错误操作,例如Call
或Name
(意思是variable_names_like_this
和function()
)。 如果您发现我遗漏了任何允许的操作,您可以简单地将它们添加到isinstance
内的元组中以允许它们。 您可以精确地自定义允许或不允许哪些语法操作。
作为对任何想在不限制您可以使用的语法的情况下使用eval
的人的公平警告,无论您的命名空间围栏如何,它都可以执行。 它获取object
类,从中获取模块以获取__builtins__
,然后获取__import__
并用它做坏事。 对于更多危险,将此处的'echo hi'
替换为'rm -rf /'
:
[v for c,v in [c for c in ''.__class__.__bases__[0].__subclasses__() if c.__name__ == 'catch_warnings'][0]()._module.__builtins__.items() if c == '__import__'][0]('os').system('echo hi')
根据文档,您遇到的错误似乎是因为:
提供的字符串或节点只能由以下 Python 文字结构组成:字符串、字节、数字、元组、列表、字典、集合、布尔值、
None
和Ellipsis
。
所以当你这样做时:
ast.literal_eval('5+5')
问题是+
这是一个BinOp
(对应于错误消息的<ast.BinOp object at 0x7d05357700>
部分)并且不能使用。
但是,当您这样做时:
ast.literal_eval(str(5+5))
评价顺序如下:
ast.literal_eval(str(5+5)) -> ast.literal_eval(str(10)) -> ast.literal_eval('10')
不再涉及+
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.