У меня есть текстовая программа, которая использует меню и подменю в стиле «while True:» l oop. Вы попадаете в подменю через верхнее меню - ИЗМЕНЕНО, чтобы включить код.
Когда я делаю выбор меню
def main():
import win32com.client, os, datetime, time, sys
outlook = win32com.client.Dispatch("Outlook.Application").GetNamespace("MAPI")
try: #THIS IS NOT THE TRY/EXCEPT BLOCK CAUSING ISSUES
itinbox = outlook.Folders("IT Department").Folders('Inbox')#Look at inbox of IT Dept inbox
itcontents = itinbox.Items #messages in the inbox
newMail = itcontents.GetLast() #GetLast is the most RECENT email.
nextMail = itcontents.GetPrevious() #The next most recent email after .GetLast()
mailSubj = newMail.Subject #The subject header
#total number of emails in the inbox
totalEmails = itcontents.Count
#print("Most recent mail:", newMail) #subject header of most recent email
#print("sent from:", newMail.Sender)
except UnicodeEncodeError: #unsupported characters
print("Most recent message had unsupported characters.")
emailUser = os.getlogin()
print("Current user is", emailUser)
#Get todays date based on system clock
todayDate = datetime.date.today()
senderDict = {email address : name} #redacted
listSender = list(senderDict.values())
listSender.insert(0, "Search Any")
def topMenu():
topMenuItems = ['Collect Attachments', 'View Senders', 'Edit Senders', 'Quit']
while True:
try:
for count, item in enumerate(topMenuItems,1):
print(count, item)
mainChoice = int(input('\nChoose an option: ')) #subtract one to match enumerate to INDEX
mainChoice -= 1
print("Chose", topMenuItems[mainChoice], "\n")
###Collect Attachments
if mainChoice == 0:
mainChoice0()
#break
elif mainChoice == 1:
print(senderDict, "\n")
input("Press any key")
continue
elif mainChoice == 2:
print("coming soon\n")
continue
elif mainChoice == 3:
input("Press any key to exit.")
sys.exit("Goodbye")
except ValueError: #Not int
print("You did not enter a valid number (ValueError)")
continue
except AttributeError:
print("You did not enter a valid number (AttributeError)")
continue
except IndexError: #outside range
print("Selection was not in the list (IndexError)")
continue
def mainChoice0(): #Collect Attachments
check = 0 #Keep count of checked messages
while True:
try:
####Determine search range by date
startDate = input("Enter a date dd-mm-yyyy: ")
while startDate == "":
startDate = input("Enter a date dd-mm-yyyy: ")
#strptime will convert startDate from a string to a usable date
startDate = datetime.datetime.strptime(startDate, "%d-%m-%Y") #class and module are called datetime hence datetime.datetime.strptime
searchRange = int(input("Enter how many days previous to search through: "))
searchDate = startDate.date() - datetime.timedelta(days = searchRange)
print("Your search starts from", startDate, "and ends on", searchDate, "\n")
#display list of senders for mainChoice == 0
for count, item in enumerate(listSender,0):
print(count, item)
print("There are", len(listSender), "options.\n")
########### Choose option from listSender
for msg in reversed(itcontents): #reversed() will go from most recent to oldest email based on date
if msg.Class == 43: #only search mail items (class 43)
#Make a folder on user desktop if it doesn't exist
if not os.path.exists("C:\\Users\\"+emailUser+"\\Desktop\\Invoices from Outlook\\"):
os.makedirs("C:\\Users\\"+emailUser+"\\Desktop\\Invoices from Outlook\\")
print("Created folder 'Invoices from Outlook' on user desktop.")
#Choose sender, reference index to name.
senderNum = int(input("Choose a sender (blank to exit): "))
senderChoice = listSender[senderNum]
#Search all
if senderNum == 0:
print("Searching for any sender")
#####Code to check emails runs after choosing a sender
#msg refers to a mail item object
if ( (str(msg.SenderEmailAddress) or str(msg.Subject) or str(msg.Sender) or str(msg.SentOnBehalfOfName)) in senderDict and (msg.SentOn.date() >= searchDate and msg.SentOn.date() <= startDate.date())):
check += 1
print(check, "messages from", msg.SenderEmailAddress, "on", msg.SentOn.date())
#Check attachment file format string, invoices are usually PDFs.
#x refers to the attachment. Not every message from a listed sender has an attachment, those messages still add to count check.
for x in msg.Attachments:
if str(".pdf").casefold() in str(x): #casfold() checks possible upper or lower case combinations e.g PdF or pDf
x.SaveAsFile("C:\\Users\\"+emailUser+"\\Desktop\\Invoices from Outlook\\" + str(msg.SentOn.date()) + str(msg.SenderEmailAddress) + x.FileName)
print("Saved attachment", x, "from", str(msg.Sender()), "on", str(msg.SentOn.date()))
#break
#Stop searching inbox earlier than searchDate
if msg.SentOn.date() < searchDate:
break
else: print("There were", check, "messages.")
#break
elif senderNum <= len(listSender) and senderNum > 0:
print("you chose", senderChoice)
##################### Search for a specific sender
##################### Need to match chosen sender to dictionary so as to only save pdfs from that sender
#senderNum != 0 for all other valid options.
#https://www.programiz.com/python-programming/methods/built-in/any
#list comprehension [x for x in [items] if y in x] https://python-3-patterns-idioms-test.readthedocs.io/en/latest/Comprehensions.html
if ( (str(msg.SenderEmailAddress) or str(msg.Subject) or str(msg.Sender) or str(msg.SentOnBehalfOfName)) in senderDict
and
(msg.SentOn.date() >= searchDate and msg.SentOn.date() <= startDate.date())
and
any([field for field in [str(msg.SenderEmailAddress), str(msg.Subject), str(msg.Sender), str(msg.SentOnBehalfOfName)] if str(senderChoice) in field])
):
check += 1
print(check, "messages from", msg.SenderEmailAddress, "on", msg.SentOn.date()) #keep count of checked messages
#Check attachment file format, invoices are usually PDFs
#x refers to the attachment. Not every message from a listed sender has an attachment, those messages still add to count check.
for x in msg.Attachments:
if str(".pdf").casefold() in str(x): #casfold() cheks upper or lower case format
x.SaveAsFile("C:\\Users\\"+emailUser+"\\Desktop\\Invoices from Outlook\\" + str(msg.SentOn.date()) + str(msg.SenderEmailAddress) + x.FileName)
print("Saved attachment", x, "from", str(msg.Sender()), "on", str(msg.SentOn.date()))
#Stop searching inbox earlier than searchDate
if msg.SentOn.date() < searchDate:
break
else: print("There were", check, "messages from", senderChoice)
elif ( senderNum != 0
and
( str(msg.SenderEmailAddress) or str(msg.Subject) or str(msg.Sender) or str(msg.SentOnBehalfOfName)) in senderDict
and
(msg.SentOn.date() >= searchDate and msg.SentOn.date() <= startDate.date())
and
any([field for field in [str(msg.SenderEmailAddress), str(msg.Subject), str(msg.Sender), str(msg.SentOnBehalfOfName)] if str(senderChoice) in field])
):
check += 1
print(check, "messages from", msg.SenderEmailAddress, "on", msg.SentOn.date()) #keep count of checked messages
#Check attachment file format, invoices are usually PDFs
#x refers to the attachment. Not every message from a listed sender has an attachment, those messages still add to count check.
for x in msg.Attachments:
if str(".pdf").casefold() in str(x): #casfold() cheks upper or lower case format
x.SaveAsFile("C:\\Users\\"+emailUser+"\\Desktop\\Invoices from Outlook\\" + str(msg.SentOn.date()) + str(msg.SenderEmailAddress) + x.FileName)
print("Saved attachment", x, "from", str(msg.Sender()), "on", str(msg.SentOn.date()))
#break
#Stop searching inbox earlier than searchDate
if msg.SentOn.date() < searchDate:
break
except UnicodeEncodeError: #unsupported characters
print("Subject line could not be parsed.")
except AttributeError: #The email was the wrong class for the attribute msg.Sender or you tried to use an attribute that doesn't work for that method
print("Attribute error (not class 43 mail) for item from", msg.SentOn.date())
continue
topMenu()
main()
Вывод выглядит так:
1 Collect Attachments
2 View Senders
3 Edit Senders
4 Quit
Choose an option: 1
Chose Collect Attachments
Enter a date dd-mm-yyyy: 21-01-2020
Enter how many days previous to search through: 7
Your search starts from 2020-01-21 00:00:00 and ends on 2020-01-14
0 Search Any
1 Hazel Blue
2 Duo Security
3 Esker Australia Pty Ltd
4 iiNet Billing Team
5 TeamViewer Sales
6 ple.com.au Gnangara Warehouse Team
7 info@thereceptionist.com.au
8 Amazon Web Services
There are 9 options.
Choose a sender (blank to exit):
You did not enter a valid number (ValueError)
Проблема в том, что ValueError не должен появляться в подменю. Это все самоучка, поэтому я полагаю, что не понимаю, как происходит обработка исключений.