簡體   English   中英

當我使用 discord.py 使用 ast.literal_eval 時,第 1 行出現格式錯誤的節點或字符串

[英]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 = 615 ** 7 = 78125 ,當然還有0.1 + 0.2 = 0.30000000000000004

不允許任何可能導致問題的錯誤操作,例如CallName (意思是variable_names_like_thisfunction() )。 如果您發現我遺漏了任何允許的操作,您可以簡單地將它們添加到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 文字結構組成:字符串、字節、數字、元組、列表、字典、集合、布爾值、 NoneEllipsis

所以當你這樣做時:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM