适当的exec命令格式化

时间:2018-04-01 18:47:29

标签: python python-3.x

我已经有了这个程序来测试exec()函数在将它放入My程序之前的行为。我期待最后我将收到一个由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)  

2 个答案:

答案 0 :(得分:1)

我怀疑有两个问题会让您的代码无法满足您的需求。主要问题是您无法使用exec直接修改函数内的局部变量。如果您在模块的顶层(全局和本地命名空间相同)中运行全局变量,可以修改全局变量。但函数中的局部变量在Python中得到了特殊处理,你不能总是把它们搞得一团糟。

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

因此,大多数locals()来电都没有效果。他们不会修改exec,因此您可以继续打印出之前的值(您初始化它的值,或者在分配该值后a,原因是I&I #39;接下来解释一下。)

另一个问题出现在"修改过的"你打电话给exec,你要将None的返回值分配给exec。这并不能达到您的期望。 a函数始终返回exec,因此这是函数其余部分的值None

如果要评估Python表达式并将其返回,请使用a而不是eval。您不能在exec中放置语句(因此只有"修改过的"调用可以按照书面形式工作)。

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

eval

如果有其他选择,使用# 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) eval通常是个坏主意。您肯定不应该exec任何您不完全信任的字符串,因为它可以运行任意Python代码。您的示例过于简单,因此无法清楚地了解您最终要尝试实现的目标,但我非常确定会为您的真正目标提供比exec更好的解决方案。 / p>

答案 1 :(得分:0)

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

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)