使用多个 if 条件时如何克服 ValueError?
How to overcome a ValueError when working with multiple if conditions?
我正在尝试制作一个可以识别文件夹名称是否为项目的脚本。为此,我想使用多个 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:以 10 为底的 int() 的无效文字:'E'
一个解决方案是创建一个快速函数来捕获错误和 returns 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
声明。可能有更有效的方法来实现此功能。
根据我对所有 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.
您可以编写一个小型解析器(诚然,可能有点过头了):
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
这是完成工作的方法,可能不是最有效的方法。
鉴于您的项目列表,
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)
我正在尝试制作一个可以识别文件夹名称是否为项目的脚本。为此,我想使用多个 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:以 10 为底的 int() 的无效文字:'E'
一个解决方案是创建一个快速函数来捕获错误和 returns 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
声明。可能有更有效的方法来实现此功能。
根据我对所有 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.
您可以编写一个小型解析器(诚然,可能有点过头了):
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
这是完成工作的方法,可能不是最有效的方法。
鉴于您的项目列表,
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)