Как преодолеть ошибку ValueError при работе с несколькими условиями if? - PullRequest
1 голос
/ 14 октября 2019

Я пытаюсь создать скрипт, который может определить, является ли имя папки проектом или нет. Для этого я хочу использовать несколько условий if. Но я борюсь с итоговой ошибкой ValueError, которая возникает, например, при проверке первой буквы имени папки и числа. Если это строка, я хочу пропустить папку и проверить следующую. Заранее всем спасибо за помощь. Привет, Бенн

Я пытался Хотя и за исключением ValueError: но не удалось с ним.

# Правильное имя для проекта "YYMM_ProjectName" = "1908_Sample_Project"

projectnames = ['190511_Waldfee', 'Mountain_Shooting_Test', '1806_Coffe_Prime_Now', '180410_Fotos', '191110', '1901_Rollercoaster_Vision_Ride', 'Musicvideo_LA', '1_Project_Win', '19_Wrong_Project', '1903_di_2', '1907_DL_2', '3401_CAR_Wagon']

# Условия проверки

for projectname in projectnames:
    if int(str(projectname[0])) < 3 and int(projectname[1]) > 5 and ((int(projectname[2]) * 10) + int(projectname[3])) <= 12 and str(projectname[4]) == "_" and projectname[5].isupper():
        print('Real Project')
        print('%s is a real Project' % projectname)
        # print("Skipped Folders")

ValueError: недопустимый литерал для int () с основанием 10: 'E'

Ответы [ 4 ]

1 голос
/ 14 октября 2019

Это то, что просто выполняет работу и, возможно, не самый эффективный способ сделать это.

Учитывая ваш список проектов,

projectnames = [
    '190511_Waldfee', 
    'Mountain_Shooting_Test', 
    '1806_Coffe_Prime_Now', 
    '180410_Fotos', 
    '191110', 
    '1901_Rollercoaster_Vision_Ride', 
    'Musicvideo_LA', 
    '1_Project_Win', 
    '19_Wrong_Project', 
    '1903_di_2', 
    '1907_DL_2', 
    '3401_CAR_Wagon'
    ]

Я вижу, что естьограниченное количество действительных строк YYMM (24 из них, чтобы быть более точным). Поэтому я сначала создаю список из этих 24 действительных YYMM.

nineteen = list(range(1900, 1913))
eighteen = list(range(1800, 1813))
YYMM = nineteen + eighteen    # A list of all 24 valid dates

Затем я немного изменяю цикл for, используя блок try-исключением-else,

for projectname in projectnames:

    try:
        first_4_digits = int(projectname[:4])  # Make sure the first 4 are digits.
    except ValueError:
        pass  # Pass silently
    else:
        if (first_4_digits in YYMM
            and projectname[4] == "_"
            and projectname[5].isupper()):
            # if all conditions are true
            print("%s is a real project." % projectname)
1 голос
/ 14 октября 2019

Из того, что я понимаю из всех ifs ... вам может быть лучше использовать regex match. Вы анализируете каждого персонажа и ожидаете, что каждый отдельный персонаж будет находиться в очень ограниченном диапазоне.

Я не проверял эту строку шаблона, поэтому она может быть неправильной или ее необходимо настроить для ваших нужд.

import re

projectnames = ['1911_Waldfee', "1908_Project_Test", "1912_WinterProject", "1702_Stockfootage", "1805_Branded_Content"]

p = ''.join(["^", # Start of string being matched
             "[0-2]", # First character a number 0 through 2 (less than 3)
             "[6-9]", # Second character a number 6 through 9 (single digit greater than 5)
             "(0(?=[0-9])|1(?=[0-2]))", # (lookahead) A 0 followed only by any number 0 through 9 **OR** A 1 followed only by any number 0 through 2
             "((?<=0)[1-9]|(?<=1)[0-2])", # (lookbehind) Match 1-9 if the preceding character was a 0, match 0-2 if the preceding was a 1
             "_", # Next char is a "_"
             "[A-Z]", #Next char (only) is an upper A through Z
              ".*$" # Match anything until end of string 
    ])

for projectname in projectnames:
    if re.match(p, projectname):
        #print('Real Project')
        print('%s is a real Project' % projectname)
        # print("Skipped Folders")

РЕДАКТИРОВАТЬ: ======================== *===== *

Вы можете перейтипошаговое тестирование шаблона с использованием следующего ...

projectname = "2612_UPPER"
p = "^[0-2].*$" # The first character is between 0 through 2, and anything else afterwards
if re.match(p, projectname): print(projectname) 
# If you get a print, the first character match is right.
# Now do the next
p = "^[0-2][6-9].*$" # The first character is between 0 through 2, the second between 6 and 9, and anything else afterwards
if re.match(p, projectname): print(projectname) 
# If you get a print, the first and second character match is right.
# continue with the third, fourth, etc. 
0 голосов
/ 14 октября 2019

Вы можете написать небольшой синтаксический анализатор (может быть, немного выше, по общему признанию):

from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor
from parsimonious.exceptions import ParseError

projectnames = ['190511_Waldfee', 'Mountain_Shooting_Test', '1806_Coffe_Prime_Now', '180410_Fotos', '191110', '1901_Rollercoaster_Vision_Ride', 'Musicvideo_LA', '1_Project_Win', '19_Wrong_Project', '1903_di_2', '1907_DL_2', '3401_CAR_Wagon']

class ProjectVisitor(NodeVisitor):
    grammar = Grammar(
        r"""
        expr    = first second third fourth fifth rest
        first   = ~"[0-2]"
        second  = ~"[6-9]"
        third   = ~"\d{2}"
        fourth  = "_"
        fifth   = ~"[A-Z]"
        rest    = ~".*"
        """
    )

    def generic_visit(self, node, visited_children):
        return visited_children or node

    def visit_third(self, node, visited_children):
        x, y = int(node.text[0]), int(node.text[1])
        if not (x * 10 + y) <= 12:
            raise ParseError

# loop over them
pv = ProjectVisitor()
for projectname in projectnames:
    try:
        pv.parse(projectname)
        print("Valid project name: {}".format(projectname))
    except ParseError:
        pass

Это дает

Valid project name: 1806_Coffe_Prime_Now
Valid project name: 1901_Rollercoaster_Vision_Ride
Valid project name: 1907_DL_2
0 голосов
/ 14 октября 2019

Одним из решений было бы создание быстрой функции, которая ловит ошибку и возвращает ложь:

def isInt(elem):
    try:
        int(elem)
        return True
    except ValueError:
        return False
...

if all(isInt(e) for e in projectname[:3]) and int(str(projectname[0])) < 3 and ...:
    ...

Или вы могли бы сначала использовать что-то вроде str.isdigit() вместо проверки своей собственной функции,во-первых, чтобы не вызывать ошибку ValueError.


Хотя на вашем месте я бы еще раз подумал, зачем вам нужен такой длинный и подробный оператор if. Возможно, есть более эффективный способ реализовать эту функцию.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...