python - 如何从另一个函数内部执行字符串内部的函数?

标签 python

我正在尝试用 Python 制作 Reddit 机器人,但我遇到了一个问题。 该机器人的目标是阅读 Reddit 搜索“get_tweets”的评论。当它找到这个时,它会阅读整个评论,看起来类似于:

get_tweets("TWITTER_USERNAME",NUMBER_OF_TWEETS,"INCLUDE_RE_TWEETS","INCLUDE_REPLIES")

评论将作为一个函数,4个参数由用户评论决定。一个例子可以是:

get_tweets("BarackObama",5,"no","yes")  

我想我已经涵盖了所有内容,除了我无法将评论作为函数执行,因为当我尝试它时会出现此错误:

SyntaxError: unqualified exec is not allowed in function 'run_bot' it contains a nested function with free variables 

这是完整的代码(除了 twitter 和 reddit 的身份验证):

keywords = ['get_tweets']
cache = []
tweets_list = []

def get_tweets(user,num,rt,rp):
    tline = api.user_timeline(screen_name=user, count=num)
    tweets = []
    for t in tline:
        reply = t.in_reply_to_screen_name
        tweet = t.text
        if rt.lower() == 'no' and rp.lower() == 'no':
            if tweet[0:2] != 'RT' and reply == None:
                tweets.append(tweet + ' | Date Tweeted: ' + str(t.created_at))
        if rt.lower() == 'yes' and rp.lower() == 'no':
            if tweet[0:2] == 'RT' and reply == None:
            tweets.append(tweet + ' | Date Tweeted: ' + str(t.created_at))
        if rt.lower() == 'no' and rp.lower() == 'yes':
            if tweet[0:2] != 'RT' and reply != None:
                tweets.append(tweet + ' | Date Tweeted: ' + str(t.created_at))
        if rt.lower() == 'yes' and rp.lower() == 'yes':
            if tweet[0:2] == 'RT' and reply != None:
                tweets.append(tweet + ' | Date Tweeted: ' + str(t.created_at))
    tweets_list = tweets

def run_bot():
    subreddit = r.get_subreddit('test')
    print('Searching...')
    comments = subreddit.get_comments(limit=100)
    for comment in comments:
        comment_text = comment.body.lower()
        isMatch = any(string in comment_text for string in keywords)
        if comment.id not in cache and isMatch:
            print('Found comment: ' + comment_text)
            exec comment_text
            cache.append(comment.id)
            start = []
            end = []
            open_p = comment.index('(')
            text = ''
            for a in re.finditer(',', comment):
                start.append(a.start())
                end.append(a.end())
            num = comment_text[end[0]:start[1]]
            user = comment_text[open_p:start[0]]
            for tweet in tweets_list:
                text.append(' | ' + tweet + '\n\n')
            if num == 1:
                reply = 'Here is the latest tweet from ' + user + ':\n\n' + text + '\n\n***\nI am a bot.'
            else:
                reply = 'Here are the last ' + num + ' tweets from ' + user + ':\n\n' + text + '\n\n***\nI am a bot.'
            comment.reply(reply)         
run_bot()

最佳答案

使用execeval 是一个巨大的安全问题!您可以尝试的最好方法是使用正则表达式从字符串中提取参数,或者使用 , 简单地分解它,然后用它调用您的函数。幸运的是,您只需要字符串和数字,因此不需要进行危险的解析。
一种可能的解决方案是:

import re

def get_tweets(user, num, rt, rp):
    num = int(num)
    print user, num, rt, rp

comment_text = 'get_tweets("BarackObama",5,"no","yes")'

# capture 5 comma separated parts between '(' and ')'
pattern = r'get_tweets\(([^,]*),([^,]*),([^,]*),([^,]*)\)'
param_parts = re.match(pattern,comment_text).groups()

# strip away surrounding ticks and spaces
user,num,rt,rp = map(lambda x:x.strip('\'" '), param_parts)

# parse the number
num = int(num)

# call get tweets
get_tweets(user,num,rt,rp)

打印:

BarackObama 5 no yes

缺点:

  • 仅当用户名不包含逗号或以 '" 开始/结束时才有效,我想这是可以假设的(如果我错了请纠正我在这里)。

优点:

  • 由于拆分是在 上完成的, 您还可以完全去掉标记,这使得 get_tweets(BarackObama,5,no,yes) 也有效。
  • 我们使用正则表达式,这意味着评论可能包含额外的文本,我们只提取我们需要的内容。
  • 如果有人想注入(inject)代码,您只会得到一个奇怪的用户名,或者错误数量的参数或一个不可解析的 int 或 rt/rp< 的无效参数... 这都会导致异常或根本没有推文。
  • 您实际上可以从 get_tweets 返回一个值,而不需要使用全局变量。

关于python - 如何从另一个函数内部执行字符串内部的函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32210270/

相关文章:

python - 如何让 django 在指定目录中查找 static 而不是 view/file.css

检测循环最终迭代的 Pythonic 方法

python - 无法使用beautifulsoup提取表数据

python - 是否有 numpy.average() 的替代方案可以在使用 numpy 时沿轴求平均值?

python - 在 Pandas 中加入 dfs 时出现关键错误

python - FTPSHook Airflow(数据通道需要 522 SSL/TLS)

python - 如何从一个 subprocess.Popen 命令同步运行多个命令?

python - 无法使用 collidepoint(event.pos) 移动图像?

python - 如何在虚拟环境中使用 pip

python - 如何在Python中使用h.264引用软件提取运动向量