Discussion:
[Tutor] email validation
Quiles, Stephanie
2015-08-01 17:54:17 UTC
Permalink
Hello All,

I have a python assignment. I have to make sure that when user inputs email that the program verifies that the address as a @ and a “.” in the entry or else return an invalid email error.
A Very rudimentary form of email validation. i cannot get the program to work. Here is what i have so far:

import pickle


def main():
cont = True
emails = open_existing_file()
print(emails)

# Get data...
while cont:
name = input("Enter your name :")
email1 = input("Enter your email address :")
email2 = input("Enter alternate email address :")
phone = input("Enter your phone number :")
contactlist = [email1,email2,phone]
emails[name] = contactlist
c = input("Enter another? [y]/n :")
if c == 'n' or c == 'N':
cont = False

def email1():
if '@' not in email and '.' not in email:
print('email needs @ and . at the same time')
# Save data...
outfile = open("emails.dat","wb")
pickle.dump(emails,outfile)
outfile.close
print("Your data has been saved to emails.dat")

def open_existing_file():
# returns an empty dictionary or one that has data from a file
emails = {}
# Load the dictionary
try:
infile = open("emails.dat","rb")
emails = pickle.load(infile)
infile.close()
except:
print("No file to open. Starting with no data.")
return emails

main()

Here is the error message :

/Library/Frameworks/Python.framework/Versions/3.4/bin/python3.4 /Users/stephaniequiles/Downloads/emailsupdate.py
Traceback (most recent call last):
File "/Users/stephaniequiles/Downloads/emailsupdate.py", line 42, in <module>
main()
File "/Users/stephaniequiles/Downloads/emailsupdate.py", line 6, in main
emails = open_existing_file()
UnboundLocalError: local variable 'open_existing_file' referenced before assignment

Process finished with exit code 1

not sure why it is not recognizing that the open_existing_file() function needs to be returned to the “emails” variable? I am guessing it has to do with my syntax? any suggestions, please?

Thank you

Stephanie Quiles



_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
ht
Válas Péter
2015-08-01 21:03:35 UTC
Permalink
Hi Stephanie,

the function should be defined first, and used after. So put it before
main().

Also, "if '@' not in email and '.' not in email:" seems to be erroneous.
You want both be present; this is an AND if you state it and becomes OR
when you deny.
if '@' not in email or '.' not in email:
In the present form your if comes true only when none of @ and . occur in
the string.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Danny Yoo
2015-08-01 21:17:57 UTC
Permalink
Post by Válas Péter
Hi Stephanie,
the function should be defined first, and used after. So put it before
main().
It's perfectly legal and ok to say:

###########################
def main():
callHelper()

def callHelper():
print("I am the helper")

main()
###########################



Rather, the problem is due to putting the helper function accidentally
nested *within* main:

############################
def main():
callHelper()

def callHelper():
print("I am the helper but can't be called until after the definition")

main()
#############################



One technical way to "fix" this is to move it up a bit:

#############################
def main():
def callHelper():
print("I am the helper but can't be called until after the definition")

callHelper()

main()
#############################



But this is usually unsatisfactory because we can't then access
callHelper from outside. There can be valid reasons to hide function
definitions at times, but this isn't one of those situations.


Válas's suggestion, to move the helper's definition above, does make sense:

#############################
def callHelper():
print("I am the helper but can't be called until after the definition")

def main():
callHelper()

main()
#############################

but a key point needs to be made: don't just move it *up*, but move it *out*.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
htt
Quiles, Stephanie
2015-08-02 01:55:49 UTC
Permalink
Thank you, the program is now working but when the email is not entered correctly it doesn’t make me go back and re-enter, it spits out an error code but then moves on to the next field .
Here is the code:

import pickle


def main():
cont = True
emails = open_existing_file()
print(emails)

# Get data...
while cont:
name = input("Enter your name :")
email1 = input("Enter your email address :")
if '@' not in email1 or '.' not in email1:
print('email needs @ and . at the same time')
cont = False
email2 = input("Enter alternate email address :")
if '@' not in email2 or '.' not in email2:
print('email needs @ and . at the same time')
cont = False
phone = input("Enter your phone number :")
contactlist = [email1, email2, phone]
emails[name] = contactlist
c = input("Enter another? [y]/n :")
if c == 'n' or c == 'N':
cont = False

def email1():
if '@' not in email1 or '.' not in email1:
print('email needs @ and . at the same time')

def email2():
if '@' not in email2 or '.' not in email2:
print('email needs @ and . at the same time')
# Save data...
outfile = open("emails.dat", "wb")
pickle.dump(emails, outfile)
outfile.close
print("Your data has been saved to emails.dat")


def open_existing_file():
# returns an empty dictionary or one that has data from a file
emails = {}
# Load the dictionary
try:
infile = open("emails.dat", "rb")
emails = pickle.load(infile)
infile.close()
except:
print("No file to open. Starting with no data.")
return emails


main()


This is the output:

/Library/Frameworks/Python.framework/Versions/3.4/bin/python3.4 /Users/stephaniequiles/Downloads/emailsupdate.py
{'maria': ['steph', 'sst', '33ed'], 'Jim': '***@ththt', 'Ton': '***@tomtom', 'Bob': '***@bob.com'}
Enter your name :sfdgh
Enter your email address :***@syesgd.com
Enter alternate email address :***@Asfdgfdcod
email needs @ and . at the same time
Enter your phone number :

I must have something missing but can’t remember what it is. Thanks for your help!

Stephanie
Post by Válas Péter
Hi Stephanie,
the function should be defined first, and used after. So put it before
main().
###########################
callHelper()
print("I am the helper")
main()
###########################
Rather, the problem is due to putting the helper function accidentally
############################
callHelper()
print("I am the helper but can't be called until after the definition")
main()
#############################
#############################
print("I am the helper but can't be called until after the definition")
callHelper()
main()
#############################
But this is usually unsatisfactory because we can't then access
callHelper from outside. There can be valid reasons to hide function
definitions at times, but this isn't one of those situations.
#############################
print("I am the helper but can't be called until after the definition")
callHelper()
main()
#############################
but a key point needs to be made: don't just move it *up*, but move it *out*.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://m
Alan Gauld
2015-08-02 08:31:58 UTC
Permalink
Post by Quiles, Stephanie
Thank you, the program is now working but when the email is not entered
correctly it doesn’t make me go back and re-enter,
it spits out an error code but then moves on to the next field .
import pickle
cont = True
emails = open_existing_file()
print(emails)
# Get data...
name = input("Enter your name :")
email1 = input("Enter your email address :")
cont = False
Instead of setting cont here - which will not stop the loop
from continuing (the while only checks the condition at the
start of each iteration) you should use continue. continue
jumps straight back to the top of the loop for another
iteration. I thnk that is what you want.

...
Post by Quiles, Stephanie
c = input("Enter another? [y]/n :")
cont = False
# Save data...
These are no longer being used. instead you create variables of the same
name which these then replace with functions. That is a recipe for
confusion. You should remove these functions. Either that or move
them outside the main block and use them in your tests. In that case you
only need one function which I'd call something like test_email()

def is_good_address(addr):
if '@' not in addr or '.' not in addr:
print('email needs @ and . at the same time')
return False
else: return True

You can then use it like

if not is_good_address(email2): continue
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/li
Alan Gauld
2015-08-02 14:12:01 UTC
Permalink
Post by Alan Gauld
them outside the main block and use them in your tests. In that case you
only need one function which I'd call something like test_email()
Ahem. Or you could call it is_good_address() of course! Oops!
Post by Alan Gauld
return False
else: return True
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos


_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Alan Gauld
2015-08-02 23:19:24 UTC
Permalink
So i took your advice and i am much closer. however, when i type in an invalid address it loops back to the first prompt and asks you to enter your name: I want it to ask you to re-enter your email address instead how would i go about this?
Just move the line that asks for the name above the while loop.
Then it will only ask for the name once.

If you want to cater for multiple users each with multiple addresses then
you will need two nested loops.

while True
user = input(...name...):
collect other user data here
while True:
get/check addresses here
name = input("Enter your name: ")
email1 = input("Enter your email address: ")
if not is_good_address(email1): continue
email2 = input("Enter an alternate email address: ")
if not is_good_address(email2): continue
phone = input("Enter your phone number: ")
contactlist = [email1, email2, phone]
emails[name] = contactlist
c = input("Enter another? [y]/n: ")
cont = False
# Save data...
outfile = open("emails.dat", "wb")
pickle.dump(emails, outfile)
outfile.close
print("Your data has been saved to emails.dat")
return False
return True
# returns an empty dictionary or one that has data from a file
emails = {}
# Load the dictionary
infile = open("emails.dat", "rb")
emails = pickle.load(infile)
infile.close()
print("No file to open. Starting with no data.")
return emails
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos

_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Quiles, Stephanie
2015-08-03 03:02:20 UTC
Permalink
ok so i made a few corrections based on what you stated and moved the name variable out of the loop. however, now its doing the same thing with alternate email. if it is entered incorrectly, it goes back to email 1 and you have to re-enter it. i tried the nested loops but they were not working either. where should i insert them into the program to make it work?
So i took your advice and i am much closer. however, when i type in an invalid address it loops back to the first prompt and asks you to enter your name: I want it to ask you to re-enter your email address instead how would i go about this?
import pickle
cont = True
emails = open_existing_file()
print(emails)
# Get data...
name = input("Enter your name: ")
email1 = input("Enter your email address: ")
if not is_good_address(email1): continue
email2 = input("Enter an alternate email address: ")
if not is_good_address(email2): continue
phone = input("Enter your phone number: ")
contactlist = [email1, email2, phone]
emails[name] = contactlist
c = input("Enter another? [y]/n: ")
cont = False
# Save data...
outfile = open("emails.dat", "wb")
pickle.dump(emails, outfile)
outfile.close
print("Your data has been saved to emails.dat")
return False
return True
# returns an empty dictionary or one that has data from a file
emails = {}
# Load the dictionary
infile = open("emails.dat", "rb")
emails = pickle.load(infile)
infile.close()
print("No file to open. Starting with no data.")
return emails
main()
Thanks
Stephanie
Post by Alan Gauld
Post by Alan Gauld
them outside the main block and use them in your tests. In that case you
only need one function which I'd call something like test_email()
Ahem. Or you could call it is_good_address() of course! Oops!
Post by Alan Gauld
return False
else: return True
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
http://www.flickr.com/photos/alangauldphotos
_______________________________________________
https://mail.python.org/mailman/listinfo/tutor
_______________________________________________
https://mail.python.org/mailman/listinfo/tutor
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Válas Péter
2015-08-03 07:12:26 UTC
Permalink
2015-08-03 5:02 GMT+02:00 Quiles, Stephanie <
Post by Quiles, Stephanie
ok so i made a few corrections based on what you stated and moved the name
variable out of the loop. however, now its doing the same thing with
alternate email. if it is entered incorrectly, it goes back to email 1 and
you have to re-enter it. i tried the nested loops but they were not working
either. where should i insert them into the program to make it work?
Now you hopefully understand the spirit of while loop.
So create two separate loops in a similar way for email1 and email2.
If you really want an alternative address, in the second loop you may check
not only validity, but that email2 is not equal to email1.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Alan Gauld
2015-08-03 07:19:01 UTC
Permalink
Post by Quiles, Stephanie
ok so i made a few corrections based on what you stated and moved the name variable out of the loop. however, now its doing the same thing with alternate email.
So you need a while loop for every element you want to validate.


while True: # overall loop per user
while True: # get user details
get and check name
while True: # email 1
get and check email1
while True: # email2
get and check email2


This is obviously repetitive so you could write a function:

get_and_check(prompt,check):
while True:
val = input(prompt)
if check(val) : return val

but since it relies on you passing in a function object (check)
that may be too advanced for you at this stage.
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.amazon.com/author/alan_gauld
Follow my photo-blog on Flickr at:
http://www.flickr.com/photos/alangauldphotos

_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Danny Yoo
2015-08-01 21:10:03 UTC
Permalink
All your function definitions should be defined with 'def' at the
leftmost margin.

However, the line in your program that starts with "def
open_existing_file()..." is not flush with the margin. Python has,
subsequently, thought that the definition of the function is scoped
locally. Move the beginning of the definition line "def
open_existing_file()" so that it's not indented.

Conceptually, what's happening is that you've accidentally written a
locally-scoped function definition, which beginner programs do not
typically do. The following program demonstrates:

---------------------------------------------------
def bigFunction():
def nestedFunction():
print("nested")

## at this point forward, nestedFunction can be accessed only
## here:
nestedFunction()
nestedFunction()

## Try calling bigFunction:
bigFunction()
## Try calling nestedFunction (and expect it to fail!)
nestedFunction()
---------------------------------------------------

Try calling bigFunction() from the toplevel. Then try calling
nestedFunction() directly from the toplevel. You'll find that you
can't: the definition of nestedFunction is scoped so that its
accessible only after the point commented.
_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
Emile van Sebille
2015-08-01 21:22:37 UTC
Permalink
Post by Quiles, Stephanie
Hello All,
import pickle
cont = True
emails = open_existing_file()
print(emails)
# Get data...
name = input("Enter your name :")
email1 = input("Enter your email address :")
email2 = input("Enter alternate email address :")
phone = input("Enter your phone number :")
contactlist = [email1,email2,phone]
emails[name] = contactlist
c = input("Enter another? [y]/n :")
cont = False
# Save data...
outfile = open("emails.dat","wb")
pickle.dump(emails,outfile)
outfile.close
print("Your data has been saved to emails.dat")
# returns an empty dictionary or one that has data from a file
emails = {}
# Load the dictionary
infile = open("emails.dat","rb")
emails = pickle.load(infile)
infile.close()
print("No file to open. Starting with no data.")
return emails
main()
/Library/Frameworks/Python.framework/Versions/3.4/bin/python3.4 /Users/stephaniequiles/Downloads/emailsupdate.py
File "/Users/stephaniequiles/Downloads/emailsupdate.py", line 42, in <module>
main()
File "/Users/stephaniequiles/Downloads/emailsupdate.py", line 6, in main
emails = open_existing_file()
UnboundLocalError: local variable 'open_existing_file' referenced before assignment
Process finished with exit code 1
not sure why it is not recognizing that the open_existing_file() function needs to be returned to the “emails” variable? I am guessing it has to do with my syntax? any suggestions, please?
Python executes as it processes the file, so that open_existing_file
must have been previously defined before you can refer to it. Try
moving that def block in front of main and you'll likely be OK (assuming
no other issues)

Emile



_______________________________________________
Tutor maillist - ***@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailm
Continue reading on narkive:
Loading...