使用多个 if 条件时如何克服 ValueError?

Posted

技术标签:

【中文标题】使用多个 if 条件时如何克服 ValueError?【英文标题】:How to overcome a ValueError when working with multiple if conditions? 【发布时间】:2020-02-11 10:05:05 【问题描述】:

我正在尝试制作一个可以识别文件夹名称是否为项目的脚本。为此,我想使用多个 if 条件。但是我对检查结果产生的 ValueError 感到困扰,例如,检查文件夹名称的第一个字母以及它是否是数字。如果它是一个字符串,我想跳过该文件夹并使其检查下一个。预先感谢大家的帮助。 干杯,本恩

我尝试了 While 和 except 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'

【问题讨论】:

问题是您在确认字符串(数字或字母)为数字或字母之前对其进行了转换。因此,您应该在将字符串转换为整数之前检查字符串是数字还是字母。你可以使用str.isdigit()。 Catch the error 并检查/打印 except 套件中的相关数据,看看出了什么问题。 需要查找异常处理 【参考方案1】:

根据我对所有 ifs 的理解...实际上,使用 regex 匹配可能会更好。您正在解析每个字符,并期望每个单独的字符都在非常有限的字符范围内。

我没有测试过这个模式字符串,所以它可能不正确或者需要根据您的需要进行调整。

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. 

【讨论】:

哇,感谢您的快速回答,我不再收到 ValueErrors 但遗憾的是它没有打印任何内容。 这意味着模式“p”不太正确。在这种情况下,re.match(p, projectname) 将在完整匹配时返回整个 projectname,如果匹配存在任何问题,则返回 None。我将在上面逐步添加一个测试您的正则表达式的方法。 您能否发布几个实际 projectname 文件名的示例,以便我们测试实际匹配? 当然我已经在上面提供了一个,但这是模式。 YY = 年(XX18、XX19(例如从 2019 年开始)MM = 月 (01 - 12),然后是下划线“_”和第一个字母大写的项目名称。名称的其余部分是随机的。所以这里有几个例子。1908_Project_Test、1912_WinterProject、1702_Stockfootage、1805_Branded_Content。希望对您有所帮助。 好的。我根据您给我的文件名再次更新了模式。他们现在都在工作。我建议您访问该链接并研究正则表达式工具。它们非常有价值! :)【参考方案2】:

这只是完成工作,可能不是最有效的方法。

鉴于您的项目列表,

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

然后我使用 try-except-else 块稍微修改你的 for 循环,

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)

【讨论】:

【参考方案3】:

您可以编写一个小型解析器(诚然,可能有点过头了):

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   = ~"\d2"
        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

【讨论】:

【参考方案4】:

一种解决方案是创建一个快速函数来捕获错误并返回 false:

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 声明。可能有更有效的方法来实现此功能。

【讨论】:

感谢您的创意和周到的回答。我用 str.isdigit() 替换了所有 int() 函数,不再出现 ValueError 问题,但它没有打印任何内容。我不知道为什么? 另外,如果有更聪明的方法可以检查前 5 个字母/数字,我愿意听取建议!

以上是关于使用多个 if 条件时如何克服 ValueError?的主要内容,如果未能解决你的问题,请参考以下文章

if函数多个条件怎么用 if函数多个条件如何使用啊

表格中IF函数如何判断多个条件

如何在 if else 循环中对同一数据使用多个条件? - java/安卓

c++如何让find_if函数能查找多个符合条件的值?

如何在 shell if 语句中表示多个条件?

如何在 Robot Framework 中编写 if 语句的多个条件