0

我希望在这里得到一些多线程帮助。我花了两天时间寻找停留在我现在的点的答案(下面代码的当前状态)。当我在 pyscripter 中运行它时,我得到了预期的打印输出(在我的线程类中),但没有生成任何错误。代码似乎无法以某种方式从线程返回。我一直处于调试模式,无法摆脱它,没有尽头。提前感谢所有帮助和耐心;这是我第一次尝试多线程。

import urllib
import urllib.error
import urllib.request
import datetime
from bs4 import BeautifulSoup
import csv
import threading
import queue

q = queue.Queue()
addrStrList = []
optionsRows = []

class OptionThread(threading.Thread):
    def __init__(self, queue):
        threading.Thread.__init__(self)
        self.queue = queue

    def run(self):
        global optionsRows
        while True:
            webString = self.queue.get()
            try:
                with urllib.request.urlopen(webString) as url: page = url.read()
                currMonth = webString[-2:]
                soup = BeautifulSoup(page)
                if (soup.text.find('There are no All Markets results for') == -1) & (soup.text.find('is no longer valid') == -1) & (soup.text.find('There is no Options data available') == -1):
                    tbls = soup.findAll('table')
                    if len(tbls[9]) > 1:
                        symb = webString[webString.find("=")+1: webString.find("&")]
                        expStrings = soup.findAll('td', text=True, attrs={'align': 'right'})[0].contents[0].split()
                        expDate = datetime.date(int(expStrings[6]), int(currMonth), int(expStrings[5].replace(',', '')))
                        calls = extract_options(tbls[9], symb, 'Call', expDate)
                        puts = extract_options(tbls[13], symb, 'Put', expDate)
                        optionsRows = optionsRows + calls
                        optionsRows = optionsRows + puts
                        print("Options extracted for: " + symb + ", ExpDate: " + str(expDate))
            except urllib.error.HTTPError as err:
                print(err.code)
                pass
##                if err.code == 404:
##                    pass
##                else:
##                    raise

class Option:
    def __init__(self, UnderlyingSymb, PutCall, Strike, Exp, Symbol, Last, Chg, Bid, Ask, Vol, OpenInt):

        self.DateDownloaded = datetime.date.today().strftime('%m/%d/%Y')
        self.UnderlyingSymb = UnderlyingSymb
        self.PutCall = PutCall
        self.Strike = Strike
        self.Exp = Exp
        self.Symbol = Symbol
        self.Last = Last
        self.Chg = Chg
        self.Bid = Bid
        self.Ask = Ask
        self.Vol = Vol
        self.OpenInt = OpenInt

    def ForCsv(self):
        return [self.DateDownloaded, self.UnderlyingSymb, self.PutCall, self.Strike, self.Exp.strftime('%m/%d/%Y'), self.Symbol, self.Last,
            self.Chg, self.Bid, self.Ask, self.Vol, self.OpenInt]

def get_month(CurrentMonth, MonthsAhead):
    cMonth = int(CurrentMonth)
    cMonthsAhead = int(MonthsAhead)
    if (cMonth + cMonthsAhead > 12):
        tempMonth = (cMonth + cMonthsAhead) - 12
    else:
        tempMonth = cMonth + cMonthsAhead
    if (tempMonth < 10):
        return '0' + str(tempMonth)
    else:
        return tempMonth

def extract_options(Options, Underlying, PutCall, Exp):
    optionList = []
    #Loop over Options to check for null values
    for op in range(1, len(Options)):

        strike = Options.contents[op].contents[0].string
        exp = Exp
        symbol = Options.contents[op].contents[1].string
        last = Options.contents[op].contents[2].string
        change = Options.contents[op].contents[3].string
        bid = Options.contents[op].contents[4].string
        ask = Options.contents[op].contents[5].string
        volume = Options.contents[op].contents[6].string
        openInt = Options.contents[op].contents[7].string

        if last == None:
            last = 0
        if change == None:
            change = 0
        if bid == None:
            bid = 0
        if ask == None:
            ask = 0
        if volume == None:
            volume = 0
        if openInt == None:
            openInt = 0

        optionList.append(Option(Underlying, PutCall, strike, exp, symbol, last, change, bid, ask,
            volume, openInt))

    return optionList

def create_address_strings():
    #read in symbol list
    with open('C:/Users/krice_000/Desktop/MarketResearch/StockSymbolsForTestingThreading.csv', 'rt') as fp:
        symbs = [s[0] for s in list(symb for symb in csv.reader(fp))]

    #loop over the symbol list and make a list of complete address strings.
    #http://finance.yahoo.com/q/op?s=HOV&m=2013-08 (Aug 2013 options chain)
    baseStr = 'http://finance.yahoo.com/q/op?s='
    dayVar = datetime.date.today()
    thisMonth = str(dayVar.month)
    thisYear = str(dayVar.year)
    for symb in symbs:
        for month in range(1,13):
            currMonth = get_month(thisMonth, month)
            if (int(currMonth) < int(thisMonth)):
                currYear = (int(thisYear) + 1)
            else:
                currYear = thisYear
            addrStrList.append(baseStr + symb + '&m=' + str(currYear) + '-' + str(currMonth))

def write_options_to_csv():
        opts = [0] * (len(optionsRows))
        for option in range(0, len(optionsRows)):
            opts[option] = optionsRows[option].ForCsv()
        #Write to the csv file.
        with open('C:/OptionsChains.csv', 'a', newline='') as fp:
            a = csv.writer(fp, delimiter=',')
            a.writerows(opts)

def run_proc():
    create_address_strings()
    for str in addrStrList:
        q.put(str)
    for i in range(5):
        t = OptionThread(q)
        #t.name = 'Thread' + str(i)
        t.setDaemon(True)
        t.start()
    q.join()
    write_options_to_csv()

if __name__ == '__main__':
    run_proc()
4

1 回答 1

1

queue.get()有一个默认参数block,默认设置为True,这意味着队列将在必要时阻塞,直到项目可用。您可以参考http://docs.python.org/2/library/queue.html了解更多信息。

原始队列获取代码可能更改为:

try:
    webString = self.queue.get(False) 
except:
    print "queue is empty"
    break
于 2013-08-13T02:50:01.490 回答