正确的exec命令格式

2024-06-02 12:45:17 发布

您现在位置:Python中文网/ 问答频道 /正文

在将exec()函数放入程序之前,我有一个程序来测试它的行为。我希望最后我会收到一个由b="last_trade_id"(在下面的例子中是13621701)表示的数字,但我得到的只是Noneost_tranzakcja

{
    "last_trade_id": 13621701,
    "product_id": "BTC-EUR",
    "sequence": 3542855617,
    "time": "2018-04-01T18:38:32.455000Z",
    "type": "heartbeat"
}
printed [a] before exec: ost_tranzakcja
printed [a] after exec: ost_tranzakcja
printed [a] after modified exec: None
printed [a] after local exec: None
printed [a] after modified local exec: None
printed [a]without and after exec: :  None

下面是我用来测试的程序:

import time
import json
from websocket import create_connection

ws=create_connection("wss://ws-feed.gdax.com")
ws.send(json.dumps({"type": "subscribe", "channels": [{"name": "heartbeat", "product_ids": ["BTC-EUR"],}]}))    


def KonektorWebsocket():
    dane=ws.recv()                                      
    dane=json.loads(dane)                               
    print(json.dumps(dane, indent=4, sort_keys=True))

    a='ost_tranzakcja'
    b="last_trade_id"

    exec("print('printed [a] before exec:', a)")

    exec("a=dane.get('"+ b +"', None)")
    exec("print('printed [a] after exec:', a)")

    a=exec("dane.get('"+ b +"', None)")
    exec("print('printed [a] after modified exec:', a)")

    exec("a=dane.get('"+ b +"', None)",locals())
    exec("print('printed [a] after local exec:', a)")

    a=exec("dane.get('"+ b +"', None)",locals())
    exec("print('printed [a] after modified local exec:', a)")

    print("printed [a]without and after exec: ", a)
while True:
    KonektorWebsocket()
    time.sleep(0.15)  

Tags: 程序noneidjsongetwslocalmodified
2条回答

有两个问题,我怀疑使你的代码不做你想要的。主要问题是不能使用exec直接修改函数中的局部变量。如果您在模块的顶层(全局和局部名称空间相同)运行它,那么它可以修改全局变量。但是函数中的局部变量在Python中得到了特殊的处理,不能总是把它们弄乱。你知道吗

除了一个exec调用外,其他所有调用都在修改locals()返回的字典(默认情况下,当不传递名称空间字典时,或者当显式传递它locals())。不幸的是,对函数中locals()的修改对名称空间中的实际变量没有任何影响,只是(暂时)在dictionary对象中。当locals()再次被调用并且命名空间中的实际值再次保存到字典中时,修改将被撤消。你知道吗

所以大多数exec调用根本没有效果。它们不会修改a,所以您会一直打印出它以前的值(要么是您初始化它的值,要么是在赋值之后None,原因我将在下面解释)。你知道吗

另一个问题是在您进行的“modified”exec调用中,您将返回值从exec分配到a。这并不是你所期望的。exec函数总是返回None,这就是a对函数其余部分的值。你知道吗

如果要计算Python表达式并返回它,请使用eval而不是exec。但是不能将语句放在eval中(因此只有“modified”调用才能像编写的那样工作)。你知道吗

以下是一些适合您的方法:

# use eval
a = eval("dane.get('" + b + "', None)")

# use a separate namespace for exec, and assign the value to a separately afterwards
namespace = {}
exec("a = dane.get('" + b + "', None)", namespace)
a = namespace['a']

# or the obvious, don't use either eval or exec, and just call the method you want directly:
a = dane.get(b, None)

如果有其他选择的话,使用evalexec通常是个坏主意。您肯定不应该exec任何您不完全信任的字符串,因为它可以运行任意Python代码。你的例子太简单了,不太清楚你到底想达到什么目的,但我很肯定,对于你真正的目标,会有比exec更好的解决方案。你知道吗

因为我的上一个示例代码过于简化,所以我提供了一个新的更复杂的版本,它可以工作并完成我想要它做的事情。(当然,除非有一种方法可以用更少的代码实现)

import time
import json
from websocket import create_connection

ws=create_connection("wss://ws-feed.gdax.com")
ws.send(json.dumps({"type": "subscribe", "channels": [{"name": "heartbeat", "product_ids": ["BTC-EUR"],}]}))
newdict={}  

def KonektorWebsocket():
    dane=ws.recv()                                      
    dane=json.loads(dane)                               
    print(json.dumps(dane, indent=4, sort_keys=True))             
    b=["last_trade_id","product_id","sequence","time","type"]
    c=['ost_tranzakcja', 'parawalut','sekwencja','czas', 'typtranzakcji']
    i=0
    while i<5:
        a = eval("dane.get('" + b[i] + "', None)")
        print(" A:    ", a)
        print(" B[i]: ", b[i])
        newdict[c[i]]=a
        i=i+1

while True:
     KonektorWebsocket()
     print(newdict)
     time.sleep(0.5) 

相关问题 更多 >