使用多个 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?的主要内容,如果未能解决你的问题,请参考以下文章