=== JoeSett is now known as JoeMaverickSett | ||
=== AlanChicken is now known as AlanBell | ||
=== Funkrat is now known as Mossyfunk | ||
=== yofel_ is now known as yofel | ||
=== nigelbabu is now known as nigelb | ||
=== starcraft is now known as starcraftman | ||
=== JanC_ is now known as JanC | ||
=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || UOW Survey: http://is.gd/fZlwL || Event: Beginners Team Dev Academy - Current Session: Introduction to Python: Part 5 - Instructors: pedro3005 | ||
pedro3005 | Hello folks | 20:00 |
---|---|---|
pedro3005 | Can whoever's here raise hands? | 20:01 |
pedro3005 | Good, good | 20:01 |
pedro3005 | Well, let me talk a bit about the class itself now | 20:02 |
pedro3005 | We're nearing the end | 20:02 |
pedro3005 | If you check out the official python tutorial, we're almost done with the basic python. From this point on they start talking about the standard library | 20:03 |
pedro3005 | Which is huge | 20:03 |
pedro3005 | So I won't be going over every detail of that | 20:03 |
pedro3005 | But with the knowledge you have from these classes, you will have no problem understanding the docs | 20:03 |
pedro3005 | hopefully | 20:03 |
pedro3005 | So last class we were talking about functions, dictionaries, files... | 20:04 |
pedro3005 | does anyone have any question or doubt? | 20:04 |
pedro3005 | Good. | 20:05 |
pedro3005 | So, today we can discuss a very important aspect of programming | 20:05 |
pedro3005 | no matter how much care you take in writing your code, things will screw up at some point | 20:06 |
pedro3005 | it happens | 20:06 |
pedro3005 | That's why we have to discuss error handling | 20:06 |
pedro3005 | Fortunately, Python has a system which makes it all easy | 20:06 |
pedro3005 | Hence exceptions! | 20:06 |
pedro3005 | An exception is an error form raised when something bad happens | 20:07 |
pedro3005 | for instance, let's look at this case | 20:07 |
pedro3005 | We learned about type conversion | 20:07 |
pedro3005 | What happens if you try to do int("a") ? | 20:07 |
pedro3005 | >>> int("a") | 20:07 |
pedro3005 | Traceback (most recent call last): | 20:07 |
pedro3005 | File "<stdin>", line 1, in <module> | 20:07 |
pedro3005 | ValueError: invalid literal for int() with base 10: 'a' | 20:07 |
pedro3005 | The most interesting part here for us is the last line | 20:08 |
pedro3005 | notice the name ValueError | 20:08 |
pedro3005 | that's the name of a python exception | 20:08 |
pedro3005 | which was raised in this case because there's no way to convert the string "a" to an int | 20:08 |
pedro3005 | This exception being raised caused our program to fail | 20:09 |
pedro3005 | now that's a very bad thing | 20:09 |
pedro3005 | But fortunately, we can catch that exception | 20:09 |
pedro3005 | that is, acknowledge in our code that if it happens, the program shouldn't crash, but instead do what you tell it to! | 20:10 |
pedro3005 | Now, how do we do that? | 20:10 |
pedro3005 | we wrap it in a try block | 20:10 |
pedro3005 | Take this example | 20:10 |
pedro3005 | we received input from the user | 20:10 |
pedro3005 | age = raw_input("What is your age? ") | 20:11 |
pedro3005 | now, he might've typed his age, a number, or maybe something else | 20:11 |
pedro3005 | if we directly try to do int(age), it might work, but it might also fail pretty bad | 20:11 |
pedro3005 | remember raw_input() is of type STRING | 20:11 |
pedro3005 | we want to make it an integer, because that makes sense for an age variable | 20:11 |
pedro3005 | So what do we do? Well, we can wrap the int(age) in a try block | 20:12 |
pedro3005 | try: | 20:12 |
pedro3005 | age = int(age) | 20:12 |
pedro3005 | except ValueError: | 20:12 |
pedro3005 | print "You didn't input a valid age" | 20:12 |
pedro3005 | You can add an else block after all the exception catches | 20:14 |
pedro3005 | that will be ran if no exception was caught | 20:14 |
pedro3005 | in this example | 20:14 |
pedro3005 | else: | 20:14 |
pedro3005 | print "The age is valid" | 20:14 |
pedro3005 | We have other built-in expressions | 20:15 |
pedro3005 | I mean exceptions | 20:15 |
pedro3005 | sorry | 20:15 |
pedro3005 | in fact you can see them all here http://docs.python.org/library/exceptions.html#bltin-exceptions | 20:15 |
pedro3005 | let's analyse for instance the case of a dictionary | 20:15 |
pedro3005 | Suppose you have a dict | 20:16 |
pedro3005 | and you try to access an element which is not there | 20:16 |
pedro3005 | >>> a = {} | 20:16 |
pedro3005 | >>> a["bla"] | 20:16 |
pedro3005 | Traceback (most recent call last): | 20:16 |
pedro3005 | File "<stdin>", line 1, in <module> | 20:16 |
pedro3005 | KeyError: 'bla' | 20:16 |
pedro3005 | It raises the KeyError exception | 20:16 |
pedro3005 | So, suppose your dict is mapping person -> age | 20:17 |
pedro3005 | but age is still type string | 20:17 |
pedro3005 | we have | 20:17 |
pedro3005 | ages = {"Joe": "20", "Mary": "30"} | 20:18 |
pedro3005 | and our program has two interfaces | 20:19 |
pedro3005 | one which allows you to input a new person and their age | 20:19 |
pedro3005 | and another one which allows you to see a person's age | 20:19 |
pedro3005 | unfortunately, some user mapped a name e.g. "Foo" to a non-numerical string, "Bar" | 20:20 |
pedro3005 | so when we try to convert that to int we'll get a ValueError expression | 20:20 |
pedro3005 | but it could happen that a user also tries to access a non-existing person in this dict | 20:20 |
pedro3005 | one min please | 20:21 |
pedro3005 | We might need to catch BOTH exceptions | 20:22 |
pedro3005 | that is easy, we just stick them in a tuple | 20:22 |
pedro3005 | that is | 20:22 |
pedro3005 | except (ValueError, KeyError): | 20:23 |
pedro3005 | handle_error() | 20:23 |
pedro3005 | assuming we have a handle_error() function here | 20:23 |
pedro3005 | the outcome isn't really important in our present analysis | 20:23 |
pedro3005 | Now, it could happen that you see something like this | 20:23 |
pedro3005 | except: | 20:23 |
pedro3005 | pass | 20:24 |
pedro3005 | Let's analyse that | 20:24 |
pedro3005 | the 'pass' keyword is a placeholder | 20:24 |
pedro3005 | you can use it when python is expecting something to be there but you don't want it to do anything | 20:24 |
pedro3005 | so 'pass' is telling python to do nothing | 20:24 |
pedro3005 | the except: statement alone will catch ANY exception | 20:24 |
pedro3005 | So this block would be saying that if any exception happens, do nothing about it | 20:25 |
pedro3005 | That is poor practice! | 20:25 |
pedro3005 | You should always try to specify the exception | 20:25 |
pedro3005 | or maybe use except: to later write it down in a log | 20:26 |
pedro3005 | To do that, you may use the traceback module | 20:28 |
pedro3005 | simply import traceback and use the command traceback.print_last() for instance, to get the last exception | 20:28 |
pedro3005 | or, if you catch it in a try block | 20:29 |
pedro3005 | you can write it to a file | 20:29 |
pedro3005 | a log file | 20:29 |
pedro3005 | traceback.print_exc(file=log) | 20:30 |
pedro3005 | assuming you have created the log file descriptor | 20:30 |
pedro3005 | Take this program, for example | 20:32 |
pedro3005 | here I will use sys.stdout so you can all see the outcome | 20:32 |
pedro3005 | but it could just as well have been any file descriptor | 20:32 |
pedro3005 | >>> import sys, traceback | 20:32 |
pedro3005 | >>> def run(): | 20:32 |
pedro3005 | ... age = raw_input("Enter your age: ") | 20:32 |
pedro3005 | ... try: | 20:32 |
pedro3005 | ... age = int(age) | 20:32 |
pedro3005 | ... except: | 20:32 |
pedro3005 | ... traceback.print_exc(file=sys.stdout) | 20:32 |
pedro3005 | ... | 20:32 |
pedro3005 | >>> run() | 20:32 |
pedro3005 | Enter your age: foo | 20:32 |
pedro3005 | Traceback (most recent call last): | 20:32 |
pedro3005 | File "<stdin>", line 4, in run | 20:32 |
pedro3005 | ValueError: invalid literal for int() with base 10: 'foo' | 20:32 |
pedro3005 | The traceback module has other functions, and as always, you can learn about them here http://docs.python.org/library/traceback.html | 20:33 |
pedro3005 | Questions? | 20:33 |
pedro3005 | Ok | 20:34 |
pedro3005 | let's have a quick look at import statements then | 20:34 |
pedro3005 | to pave the road for modules | 20:34 |
pedro3005 | We have been using them for a while | 20:35 |
pedro3005 | the import statement brings a module into your program | 20:35 |
pedro3005 | for instance | 20:35 |
pedro3005 | >>> import math | 20:35 |
pedro3005 | >>> math.sqrt(math.pi) | 20:35 |
pedro3005 | 1.7724538509055159 | 20:35 |
pedro3005 | we can also use the 'as' keyword | 20:35 |
pedro3005 | >>> import math as magic | 20:36 |
pedro3005 | >>> magic.sqrt(10) | 20:36 |
pedro3005 | 3.1622776601683795 | 20:36 |
pedro3005 | and we have the 'from' keyword | 20:37 |
pedro3005 | we can use that to import only a specific attribute we want | 20:37 |
pedro3005 | >>> from math import cos | 20:38 |
pedro3005 | >>> cos(0) | 20:38 |
pedro3005 | 1.0 | 20:38 |
pedro3005 | notice we did cos(0) and not math.cos(0) | 20:38 |
pedro3005 | because with the 'from' keyword we're importing it directly onto our namespace | 20:38 |
pedro3005 | similarly you can use * to mean everything | 20:38 |
pedro3005 | >>> from math import * | 20:40 |
pedro3005 | >>> sqrt(factorial(5)) | 20:40 |
pedro3005 | 10.954451150103322 | 20:40 |
pedro3005 | Questions? | 20:41 |
pedro3005 | Good | 20:42 |
pedro3005 | You can import your own file | 20:42 |
pedro3005 | for instance | 20:42 |
pedro3005 | let's say you made a function which checks if a number is odd | 20:43 |
pedro3005 | in your file odd.py | 20:43 |
pedro3005 | def is_odd(x): | 20:43 |
pedro3005 | return x % 2 != 0 | 20:44 |
pedro3005 | let's look at that function closer | 20:44 |
pedro3005 | it seems a bit weird | 20:44 |
pedro3005 | but it makes sense | 20:44 |
pedro3005 | x % 2 != 0 is a boolean expression | 20:44 |
pedro3005 | it will be evaluated to either True or False | 20:44 |
pedro3005 | and that's what we return | 20:44 |
pedro3005 | any questions about that? | 20:44 |
pedro3005 | good | 20:45 |
pedro3005 | now, in a python terminal we can import that file | 20:45 |
pedro3005 | if we open it in the same folder | 20:46 |
pedro3005 | >>> import odd | 20:46 |
pedro3005 | >>> odd.is_odd(5) | 20:46 |
pedro3005 | True | 20:46 |
pedro3005 | now let's look at a line present in many python scripts | 20:48 |
pedro3005 | if you have analyzed some, you maybe have noticed it | 20:48 |
pedro3005 | towards the bottom it has something like | 20:48 |
pedro3005 | if __name__ == "__main__": | 20:48 |
pedro3005 | What does that mean? | 20:48 |
pedro3005 | It basically checks if the script was called directly "python odd.py" or imported | 20:48 |
pedro3005 | if it was imported, the if check fails | 20:48 |
pedro3005 | so let's suppose that if someone runs 'python odd.py' you want to display the message "Welcome to odd.py" | 20:49 |
pedro3005 | but if someone imports it from another program or shell, then do nothing | 20:49 |
pedro3005 | let's add that line | 20:49 |
pedro3005 | if __name__ == "__main__": | 20:49 |
pedro3005 | print "Welcome to odd.py!" | 20:49 |
pedro3005 | now if we run it directly, we get the message | 20:50 |
ClassBot | There are 10 minutes remaining in the current session. | 20:50 |
pedro3005 | [pedro@pedro ~]$ python odd.py | 20:50 |
pedro3005 | Welcome to odd.py! | 20:50 |
pedro3005 | but if we import it instead | 20:50 |
pedro3005 | >>> import odd | 20:50 |
pedro3005 | >>> | 20:50 |
pedro3005 | nothing :) | 20:50 |
pedro3005 | So to end today let's talk about command line arguments | 20:51 |
pedro3005 | they're like when you call a program with certain parameters | 20:51 |
pedro3005 | 'ls -a' | 20:51 |
pedro3005 | -a is an argument | 20:51 |
pedro3005 | just like in a function | 20:51 |
pedro3005 | our python programs can have that to | 20:51 |
pedro3005 | first we need to import the module sys | 20:52 |
pedro3005 | import sys | 20:52 |
pedro3005 | then, the arguments can be accessed in sys.argv | 20:52 |
pedro3005 | let's try that | 20:52 |
pedro3005 | in our arg.py file we have | 20:53 |
pedro3005 | import sys | 20:53 |
pedro3005 | print sys.argv | 20:53 |
pedro3005 | so let's call it | 20:53 |
pedro3005 | [pedro@pedro ~]$ python arg.py these are arguments | 20:53 |
pedro3005 | ['arg.py', 'these', 'are', 'arguments'] | 20:53 |
pedro3005 | well | 20:54 |
pedro3005 | what if I set that as executable via chmod | 20:55 |
pedro3005 | then I need to add our good old shebang line | 20:55 |
pedro3005 | #!/usr/bin/env python | 20:55 |
ClassBot | There are 5 minutes remaining in the current session. | 20:55 |
pedro3005 | to the start of our program | 20:55 |
pedro3005 | and by calling it the exact same way we get the same thing | 20:55 |
pedro3005 | [pedro@pedro ~]$ ./arg.py these are arguments | 20:55 |
pedro3005 | ['./arg.py', 'these', 'are', 'arguments'] | 20:55 |
pedro3005 | Now, if you're a C programmer, you might be wondering about sys.argc, but that is not needed. Since we have a great list functionality, we can merely use len(sys.argv) | 20:56 |
pedro3005 | which is the count of how many command line arguments we have | 20:56 |
pedro3005 | Questions? | 20:56 |
pedro3005 | Well, good | 20:58 |
pedro3005 | that marks the end of today's session | 20:58 |
pedro3005 | Hope you all had a good time | 20:59 |
pedro3005 | thanks for the attention | 20:59 |
ClassBot | Logs for this session will be available at http://irclogs.ubuntu.com/2010/10/16/%23ubuntu-classroom.html | 21:00 |
=== ChanServ changed the topic of #ubuntu-classroom to: Welcome to the Ubuntu Classroom - https://wiki.ubuntu.com/Classroom || Support in #ubuntu || Upcoming Schedule: http://is.gd/8rtIi || Questions in #ubuntu-classroom-chat || UOW Survey: http://is.gd/fZlwL || | ||
palhmbs | where are logs for this channel? | 21:00 |
palhmbs | ah - never mind | 21:00 |
palhmbs | how long does it take for logs to be populated? | 21:01 |
nigelb | palhmbs: should be ready now | 21:04 |
palhmbs | yep - got them | 21:04 |
palhmbs | thanks | 21:04 |
palhmbs | only just found about this - #ubuntu-classroom thing - it's awesome | 21:05 |
nigelb | \o/ | 21:05 |
palhmbs | nigelb, your involved with the Ubuntu Youth team? | 21:05 |
nigelb | palhmbs: no, but I am involved with the classroom team | 21:06 |
palhmbs | I'm 32, is their a middle-aged group for beginners? | 21:06 |
nigelb | well, there's the beginners team | 21:06 |
nigelb | https://wiki.ubuntu.com/BeginnersTeam | 21:06 |
palhmbs | ah, I want to be more involved with Ubuntu, help - I've joined Openhatch.org - heard of it? | 21:07 |
nigelb | yeah, paulproteus wrote it | 21:07 |
palhmbs | I've been trying to get Gobby-0.5 connecting to gobby's main server.... | 21:09 |
palhmbs | would gobby be a good way to teach programming? | 21:10 |
nigelb | It would if you can find someone willing to teach :) | 21:12 |
palhmbs | nigelb, do you know when the calendar will be updated, I don't see any stuff for the next 2 weeks? | 21:37 |
nigelb | palhmbs: that's because there isn't anything for the next 2 weeks | 21:38 |
palhmbs | nigelb, oh well, gives me opportunity to read the logs for the next 2 weeks.... I suppose | 21:40 |
nigelb | heh :) | 21:40 |
=== JoeSett is now known as JoeMaverickSett |
Generated by irclog2html.py 2.7 by Marius Gedminas - find it at mg.pov.lt!