Ошибка типа: «<» не поддерживается между экземплярами «str» и «float» - Prettytable Error - PullRequest
0 голосов
/ 26 февраля 2020

Я получаю вышеуказанную ошибку при попытке запустить мой скрипт Py. Это также выдает ошибку в довольно стабильном коде, что также странно, так как я все время использую его нормально. По сути, это веб-скрипт, который я сделал для использования с игрой менеджера авиакомпании, в которую я играю.

Код:

if "top" in str(r): # log-in was successful.
   if True: # just to make it collapsible
    def getHTML(url):
        return http.request('GET', url, headers={'Cookie': 'PHPSESSID='+phpSid}).data

    def findBetween1(s, start, end):
        try:
            return str((s.split(start))[1].split(end)[0])
        except:
            return ""

    def getHTMLthreaded(infoArray): # infoArray: [url, detail, detail]
        def getHTML(url):
            return http.request('GET', url, headers={'Cookie': 'PHPSESSID='+phpSid}).data

        with ThreadPoolExecutor(max_workers=threads) as executor:
            futureToURL = {executor.submit(getHTML, info): info for info in infoArray}
            responseResults = []
            for future in as_completed(futureToURL):
                responseResults.append(future.result()) # [data, url]

        return responseResults

    def median(lst):
        lst = [int(i) for i in lst]
        n = len(lst)
        s = sorted(lst)
        return int((sum(s[n//2-1:n//2+1])/2.0, s[n//2])[n % 2]) if n else None

acURLs = []
fleet = BeautifulSoup(getHTML('https://www.airline4.net/fleet.php?undefined'), "lxml").find_all(onclick=re.compile('Ajax')) # get a list of fleet

for acTypeId in fleet:
    acURLs.append('https://www.airline4.net/fleet.php?type='+findBetween1(str(acTypeId), 'type=', "'")) # for each fleet type, get a list of aircraft belonging to that type

acMenus = getHTMLthreaded(acURLs)

# t = PrettyTable([])
acIds = []
for acMenu in acMenus:
    acMenuItems = BeautifulSoup(acMenu, "lxml").find_all(onclick=re.compile('routes_main.php'))
    for thisAcMenu in acMenuItems:
        acIds.append('https://www.airline4.net/fleet_details.php?id='+findBetween1(str(thisAcMenu['onclick']), 'id=', "','"))

# acIds = ['https://www.airline4.net/fleet_details.php?id=1323552']

print('Sorting by "profit/pax", indicating how well the route actually profits.')
t = PrettyTable(['model', 'reg', 'chkH', 'wear', 'config', 'fn', 'route', u'$\u02dc', u'CO\u2082\u02dc', 'fuel', 'prof/pax', 'prof/hrs'])

acDetails = getHTMLthreaded(acIds)
for acDet in acDetails:
    acDet = BeautifulSoup(acDet, "lxml")

    mainTable = acDet.find(class_='col-sm-6 bg-light border').find_all(class_='m-text')
    seatLayout = acDet.find_all(class_='col-4 p-2 text-center exo')

    acType = str(mainTable[0].string)
    fleetReg = str(acDet.find(id='ff-name').string)
    chk = str(mainTable[2].string) # hours to check
    wear = str(mainTable[6].string) # wear percentage
    yS = str(seatLayout[0].find('br').next_sibling.strip().rjust(3))
    jS = str(seatLayout[1].find('br').next_sibling.strip().rjust(3))
    fS = str(seatLayout[2].find('br').next_sibling.strip().rjust(3))
    config = yS + "/" + jS + "/" + fS
    try: # in case the aircraft is not routed:
        routeReg = str(acDet.find(id='rr-name').string)
        stop = str(acDet.find(class_='xs-text pt-2')).replace('<div class="xs-text pt-2">Via<br/> ','').replace('</div>','')
        stop = "" if stop == "None" else "·" + stop
        route = str(acDet.find_all(class_='l-text exo')[0].string) + stop + "·" + str(acDet.find_all(class_='l-text exo')[1].string)

        inc, co2 = [], []
        for thisFlight in acDet.find_all(class_='row bg-light m-text p-1 border'):
            inc.append(str(thisFlight.find(class_='col-3 text-right text-success').find('b').string).replace('$', '').replace(',', ''))
            co2.append(str(thisFlight.find(class_='s-text').string).replace(' Quotas', '').replace(',', ''))
            prices = thisFlight.find_all(class_='col-3')[2]

        inc, co2 = median(inc), median(co2)
        fuel = str(acDet.find(class_='row bg-light m-text p-1 border').find_all(class_='s-text')[1].string).replace(' Lbs', '').replace(',', '')
        profit = inc - (co2 * co2Price / 1000) - (int(fuel) * fuelPrice / 1000)

        depTime = acDet.find_all(class_='col-6 bg-white border s-text')[0].string.strip().replace(' UTC', '').split(':')
        arrTime = acDet.find_all(class_='col-6 bg-white border s-text')[1].string.strip().replace(' UTC', '').split(':')

        depSec = int(depTime[0])*3600 + int(depTime[1])*60 + int(depTime[2])
        arrSec = int(arrTime[0])*3600 + int(arrTime[1])*60 + int(arrTime[2])
        hrsElapsed = ((86400 - (depSec - arrSec)) if depSec > arrSec else arrSec - depSec) / 3600

        profPax = round(profit / (int(yS) + int(jS)*2 + int(fS)*3),3)
        profHrs = round(profit / hrsElapsed, 3)

        t.add_row([acType, fleetReg, chk, wear, config, routeReg, route, inc, co2, fuel, profPax, profHrs])
    except: # only show the fleet details, but no other metrics
        # print(sys.exc_info()[0])
        t.add_row([acType, fleetReg, chk, wear, config, "", "", "", "", "", "", ""])

t.sortby = 'prof/pax'
print(t)

else:
print('Your e-mail and/or password was wrong.')

Трассировка:

Traceback (most recent call last):
  File "dX.py", line 123, in <module>
    print(t)
  File "C:\Users\SSM\AppData\Local\Programs\Python\Python38\lib\site-packages\prettytable.py", line 237, in __str__
    return self.__unicode__()
  File "C:\Users\SSM\AppData\Local\Programs\Python\Python38\lib\site-packages\prettytable.py", line 243, in __unicode__
    return self.get_string()
  File "C:\Users\SSM\AppData\Local\Programs\Python\Python38\lib\site-packages\prettytable.py", line 984, in get_string
    rows = self._get_rows(options)
  File "C:\Users\SSM\AppData\Local\Programs\Python\Python38\lib\site-packages\prettytable.py", line 933, in _get_rows
    rows.sort(reverse=options["reversesort"], key=options["sort_key"])
TypeError: '<' not supported between instances of 'str' and 'float'

1 Ответ

0 голосов
/ 26 февраля 2020

Когда вы обрабатываете исключение, вы добавляете значение по умолчанию, которое нельзя сравнить с вашими числами с плавающей точкой:

except:
    t.add_row([acType, fleetReg, chk, wear, config, "", "", "", "", "", "", ""])
    #                       these are all strings   ^^  ^^  ^^  ^^  ^^  ^^  ^^

Если вы хотите отсортировать по столбцу prof/pax, вы нужно указать в этом столбце только цифры c значения . Возможно, вам вполне подойдет 0?

except:
    t.add_row([acType, fleetReg, chk, wear, config, "", "", "", "", "", 0, ""])
    #                                        numeric value for profPax ^^

В качестве альтернативы вы можете указать ключ сортировки , вызываемый для преобразования каждого значения в отсортированном столбце во что-то для сравнения. Вы можете использовать это, чтобы заменить строки нулями только при сортировке :

t.sort_key = lambda value: value or 0

Это использует тот факт, что оба "" и 0 являются ложными-y и так or выберет второе возвращаемое значение, 0:

>>> value = ""
>>> value or 0
0

Примечание: это редко хорошая идея использовать except: без квалификации. Если ваш код имеет, скажем, проблемы с нулевым делением, перехватывает только это исключение :

except ZeroDivisionError:
     t.add_row([acType, fleetReg, chk, wear, config, "", "", "", "", "", "", ""])

Вы всегда можете добавить больше исключений; Ваш код потенциально может вызвать ValueError s (из int() преобразований и т. п.) и AttributeError (из-за попытки обработать None значения, как будто они являются элементами BeautifulSoup, например), так что вы можете поймать только эти 3 :

except (ZeroDivisionError, ValueError, AttributeError):
     t.add_row([acType, fleetReg, chk, wear, config, "", "", "", "", "", "", ""])

Это значительно упростит обнаружение ошибок в вашем коде в дальнейшем и позволит вам легче прерывать вашу программу, если она занимает много времени. не перехватывает исключение KeyboardInterrupt.

...