Python 调用_umain中的While循环函数?

Python 调用_umain中的While循环函数?,python,function,while-loop,python-multithreading,Python,Function,While Loop,Python Multithreading,这里我有一个程序,它轮询队列中的一个事件,如果发现它,它将执行一个RESTAPI命令。此外,如果发现事件,它会打印当前价格,我需要将其用作止损。这段代码完全按照我希望的方式运行,但是,当我尝试调用\uuuuu main\uuuu中的函数rates()时,程序就会停止运行 删除引用stopLoss=rates(),程序在没有stopLoss的情况下运行良好,但我需要速率-.001作为我的stopLoss 代码如下: import Queue import threading import time

这里我有一个程序,它轮询队列中的一个事件,如果发现它,它将执行一个RESTAPI命令。此外,如果发现事件,它会打印当前价格,我需要将其用作止损。这段代码完全按照我希望的方式运行,但是,当我尝试调用
\uuuuu main\uuuu
中的函数
rates()
时,程序就会停止运行

删除引用
stopLoss=rates()
,程序在没有
stopLoss
的情况下运行良好,但我需要速率
-.001
作为我的
stopLoss

代码如下:

import Queue
import threading
import time
import json
import oandapy

from execution import Execution
from settings import STREAM_DOMAIN, API_DOMAIN, ACCESS_TOKEN, ACCOUNT_ID
from strategy import TestRandomStrategy
from streaming import StreamingForexPrices

#polls API for Current Price
def stop():
        while True:
            oanda = oandapy.API(environment="practice", access_token="xxxxxx")
            response = oanda.get_prices(instruments="EUR_USD")
            prices = response.get("prices")
            asking_price = prices[0].get("ask")
            s = asking_price - .001
            return s

#Checks for events and executes order                
def trade(events, strategy, execution):
    while True:
        try:
            event = events.get(False)
        except Queue.Empty:
            pass
        else:
            if event is not None:
                if event.type == 'TICK':
                    strategy.calculate_signals(event)
                elif event.type == 'ORDER':
                    print 
                    execution.execute_order(event)

def rates(events):
            while True:
                try:
                    event = events.get(False)
                except Queue.Empty:
                    pass
                else:
                        if event.type == 'TICK':
                                r = stop()
                                print r

if __name__ == "__main__":
    heartbeat = 0  # Half a second between polling
    events = Queue.Queue()

# Trade 1 unit of EUR/USD
    instrument = "EUR_USD"
    units = 1
    stopLoss = rates()  #Problem area!!!!!!>>>>>>>>>>>>>>//////////////////////////

    prices = StreamingForexPrices(
        STREAM_DOMAIN, ACCESS_TOKEN, ACCOUNT_ID,
        instrument, events
    )
    execution = Execution(API_DOMAIN, ACCESS_TOKEN, ACCOUNT_ID)

    strategy = TestRandomStrategy(instrument, units, events, stopLoss)


#Threads
    trade_thread = threading.Thread(target=trade, args=(events, strategy, execution))
    price_thread = threading.Thread(target=prices.stream_to_queue, args=[])
    stop_thread = threading.Thread(target=rates, args=(events,))      

# Start both threads
    trade_thread.start()
    price_thread.start()
    stop_thread.start()

好的,到目前为止还没有答案,所以我会试试。
您的主要问题似乎是,您不知道如何在线程之间交换数据。
首先是价格问题

这里的循环:

while True:
    oanda = oandapy.API(environment="practice", access_token="xxxxxx")
    response = oanda.get_prices(instruments="EUR_USD")
    prices = response.get("prices")
    asking_price = prices[0].get("ask")
    s = asking_price - .001
    return s
没有效果,因为
返回s
将自动中断。 因此,您需要的是一个共享变量,用于存储
s
。您可以使用
threading.Lock
来保护对它的访问。最简单的方法是将Thread子类化,并使
s
成为这样的实例属性(我将其命名为
price
):

然后可以从以下内容开始:

poller = PricePoller(heartbeat)
poller.start()
您可以使用
poller.price
随时随地获取价格!如果愿意,您甚至可以将轮询器传递到其他线程。 但是如果您试图在poller.start()之后立即获得价格,您肯定会得到一个
None
。为什么会这样
poller.start()
不会阻塞,因此当您的主线程继续运行并尝试获取第一个价格时,您的轮询器甚至还没有完成启动
如何解决这个问题?引入另一个
threading.Event
,并使用其函数
wait
让主线程等待,直到轮询器线程设置它为止。我把实现交给你

我只是猜测这就是你想要的。。。只看你的代码,你根本不必把
stop
函数放在线程中,你可以用
stopLess=rates()
替换
stopLess=stop()
,因为你不会在任何地方更新价格轮询的结果!但我认为你想在某个时候这样做,否则把它放到线程中是没有意义的

现在转到队列和您的“事件流”。
这个片段:

try:
    event = events.get(False)
except Queue.Empty:
    pass
也可以是:

event = events.get()
无论如何,在此期间你什么也没做,最好让
排队
来处理等待事件。
然后,据我所知,您有两个线程调用
Queue.get
,但是此函数将在检索该元素后从队列中删除该元素!这意味着谁先获得事件,谁就消费它,而另一个线程将永远看不到它。但是使用上述轮询器解决方案,我认为您可以摆脱
停止线程
,这也解决了这个问题

现在是关于线程的一般说明。
一个线程有它自己的调用“链”,它从它的
run
方法(或者如果你没有子类化的话,你作为
target
提供的方法)开始。 这意味着由
run
调用的任何函数都由该线程执行,也包括由该线程依次调用的所有函数(依此类推)。但是,两个线程完全有可能同时执行同一个函数!如果不使用同步手段(例如事件、锁或屏障),则无法知道哪个线程在特定时间执行代码的哪个部分。 如果调用函数中使用的所有变量都是本地变量或调用函数中使用的所有变量都是本地变量,则这没有问题:

def onlyLocal(x, n):
    if n == 0:
        return x
    return onlyLocal(x*2, n-1)
或专门阅读:

def onlyRead(myarray):
    t = time.time()
    return t - sum(myarray)
但是,一旦从多个线程读取和写入变量,就需要确保对这些变量的访问安全,否则,如果传递多个线程已知的对象(例如
self
):

或者,如果函数使用由多个线程访问的外部范围中的变量:

def variableFromOutside(y):
    global x
    x += y
    return y
在处理变量时,在用无效值更新变量之前,您永远无法确定没有线程(2)更改您(1)刚刚读取的变量

global x ; Thread1 ;  Thread2 ;
    2    ;  y = x  ;   z = x  ;
    2    ; y **= 3 ;  x = z+1 ;
    3    ; x = y-4 ;   return ;
    4    ;  return ;   ...    ;
这就是为什么必须使用锁来保护对这些变量的访问。带锁(
l
):

此处,Thread1在Thread2之前获取锁。因此,Thread2必须等到Thread1再次释放锁后,才能返回对
acquire
的调用。
使用带锁的
时,会自动调用
获取
释放
。
还请注意,在这个玩具示例中,可能是Thread2在Thread1之前触发锁,但至少它们不会相互干扰

这是一个大主题的简要介绍,阅读一些关于线程并行化的内容,并尝试使用它。没有比实践更好的学习方法了。

我在浏览器中编写了这段代码,因此它未经测试!如果有人发现问题,请在评论中告诉我,或者直接更改。

您确定没有任何例外吗?据我所见,您的
stopLoss=rates()
行应该会引发
TypeError
,因为您没有提供
events
参数。。。您可能希望删除括号以获取对该方法的引用,而不是调用它;)是的,你是对的,我确实收到了一个错误“收到的请求的正文格式不正确:'units=1&instrument=EUR_USD&type=market&side=buy&stopLoss=%3Cfunction+rates+at+0x1040f9f50%3E'”。当我像这样运行它时,“stopLoss=rates(events)”,什么都没有发生。。它就是不运行?是的,当然什么也没发生,当你陷入
速率
的循环中时,没有人来填充你的队列。。。我认为你的问题是,你还没有理解线程是如何工作的。不幸的是,我不知道
def variableFromOutside(y):
    global x
    x += y
    return y
global x ; Thread1 ;  Thread2 ;
    2    ;  y = x  ;   z = x  ;
    2    ; y **= 3 ;  x = z+1 ;
    3    ; x = y-4 ;   return ;
    4    ;  return ;   ...    ;
global x ;    Thread1   ;   Thread2   ;
    2    ; l.acqcuire() ; l.acquire() ;
    2    ; y = x        ;      |      ;
    2    ; y **= 3      ;      |      ;
    2    ; x = y-4      ;      |      ;
    4    ; l.release()  ;      v      ;
    4    ; return       ; z = x       ;
    4    ; ...          ; x = z+1     ;
    5    ; ...          ; l.release() ;