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