I decided to just bite the bullet and reorganize the program I'm writing to make some reporting easier at work. Python project organization is a pain.
http://stackoverflow.com/questions/391879/organising-my-python-project
http://stackoverflow.com/questions/1642975/folder-and-file-organization-for-python-development
http://www.python.org/doc/essays/packages.html
I think I have it figured out, and some of the problems I had with importing my modules last night might have been operating system specific. I'm doing the development in OSX since I don't want to boot into my Linux VM every time I want to bang out an idea.
I'm using Excel for 90% of the reporting right now due to time constraints. I'd LOVE to do it 100% in Python so that I can do much more elaborate and flexible reporting. The last 10% is yanking out some numbers based off how long a case takes to close so that I can make a histogram. I spent way too long trying to get Excel to do that and failed. It's going to be much easier using Python, but I'm making it harder than it needs to be so that I can set up a solid library of functions I want to use in the future.
I'm 28 (oops, 29 now) and I want to be C literate by the time I'm 30. That's two (one) years to become competent at something I've been wanting to do nearly my whole life. No pressure.
Showing posts with label python. Show all posts
Showing posts with label python. Show all posts
Wednesday, March 28, 2012
Thursday, February 16, 2012
Reading bytes in Python
Today's lesson in why you should RTFM, but more on that later.
One of the biggest successes I had while learning C was reading text and binary data from files. I'm going to tackle the same task in Python. The first step is going to be reading in some data (the first 136 bytes) of the file header.
The file I'm reading is the same sort of file I learned to read in C - a file with some header data with various things like the date it was acquired and some comments, and then large chunks of digitized analog data (like a .wav file in a way).
I'm starting small - I only want to read in the first 136 bytes of the file. The first 4 bytes represent an integer that is always in the file (sort of a marker that tells us where it came from). The next 4 bytes is the version of the file format (also an integer), and the next 128 bytes represent a string of 128 characters (which are 1 byte each, so 128 characters).
I've spent a good deal of time prepping for this task - most of the info I needed was in the documentation for file objects and the struct module. In short, I'm going to read in a known number of bytes using the read() method for file objects, and then "unpack" those bytes into a specific format (integers and character strings) using the unpack() function in the struct module. So, here's a start:
I once read somewhere that using a class full of empty instance (self) variables is a good way to mimic how structures in C look. I don't know if that's very "Pythonic" but it works for me. In the PHeader class I've defined three variables that I'm going to fill in with data from the file. The actual code that executes is under "if __name__ == '__main__'", which is just a fancy Python way of saying "if this .py file is run on its own then do what's underneath".
First I open the file as "p", and initialize "s" as an instance of PHeader. I know that p.read(N) will read in N bytes of the file, so I need to somehow tell Python to interpret those four bytes as an integer (as opposed to another data type that is 4 bytes) and then make s.MagicNumber equal that resulting number.
So that's where the struct module's unpack() function comes in. unpack() has this prototype: unpack(fmt, string). fmt is the format of the bytes being read (we want an integer so we pass it "i") and string is the bytes to unpack. Well, the result of p.read(4) is our string, so this line...
s.MagicNumber = unpack('i', (p.read(4)))
...gets our four bytes, interprets that as an integer, and passes the result to s.MagicNumber. A big caveat that I missed while writing this that caused a great deal of confusing is that it doesn't ACTUALLY pass JUST the integer. It passes a Python data type called a tuple with the integer I wanted as the first element of that tuple. Tuples (and other Python data types) work a lot like arrays in other languages - but more on that in a second.
The next line does pretty much the same thing...
s.Version = unpack('i', (p.read(4)))
Ok cool, we have now read two integers from the file and stored them in some variables. This next part is tricky and caused a lot of wailing and gnashing of teeth on my part. The struct documentation told me that "i" is the format character for integers, and "s" is the format character for character arrays (strings). Since the next 128 bytes of the file is a row of 128 characters (a string) I figured I could just replace the "i" with an "s" and then do p.read(128). This was incorrect. After a lot of pondering over error messages I carefully read through the struct module documentation and found that you have to precede the "s" with the number of characters to be read, like "128s". So that resulted in this line...
s.Comment = unpack('128s', (p.read(128)))
...and all was well.
Remember I said that unpack() returns a tuple, and in our case the first element of that tuple is that actual integer or character array we asked for from the file? Getting the first element out of a tuple is a lot like getting the first element out of a C array. If I have a tuple called MyTuple I can get the first element by asking for MyTuple[0]. So the print lines...
print('Magic Number: %s') % hex(s.MagicNumber[0])
print('Version: %d') % s.Version[0]
print('Comment: %s') % s.Comment[0]
...do exactly that. Oh - the first line says hex(s.MagicNumber[0]) because I want the integer returned to be printed out as a hexadecimal number.
All said and done that dozen lines of code took about an hour, which isn't bad considering I started out with only a superficial knowledge of how to read bytes. Hopefully the next step of reading the more important data from the file won't be so traumatic now.
One of the biggest successes I had while learning C was reading text and binary data from files. I'm going to tackle the same task in Python. The first step is going to be reading in some data (the first 136 bytes) of the file header.
The file I'm reading is the same sort of file I learned to read in C - a file with some header data with various things like the date it was acquired and some comments, and then large chunks of digitized analog data (like a .wav file in a way).
I'm starting small - I only want to read in the first 136 bytes of the file. The first 4 bytes represent an integer that is always in the file (sort of a marker that tells us where it came from). The next 4 bytes is the version of the file format (also an integer), and the next 128 bytes represent a string of 128 characters (which are 1 byte each, so 128 characters).
I've spent a good deal of time prepping for this task - most of the info I needed was in the documentation for file objects and the struct module. In short, I'm going to read in a known number of bytes using the read() method for file objects, and then "unpack" those bytes into a specific format (integers and character strings) using the unpack() function in the struct module. So, here's a start:
I once read somewhere that using a class full of empty instance (self) variables is a good way to mimic how structures in C look. I don't know if that's very "Pythonic" but it works for me. In the PHeader class I've defined three variables that I'm going to fill in with data from the file. The actual code that executes is under "if __name__ == '__main__'", which is just a fancy Python way of saying "if this .py file is run on its own then do what's underneath".
First I open the file as "p", and initialize "s" as an instance of PHeader. I know that p.read(N) will read in N bytes of the file, so I need to somehow tell Python to interpret those four bytes as an integer (as opposed to another data type that is 4 bytes) and then make s.MagicNumber equal that resulting number.
So that's where the struct module's unpack() function comes in. unpack() has this prototype: unpack(fmt, string). fmt is the format of the bytes being read (we want an integer so we pass it "i") and string is the bytes to unpack. Well, the result of p.read(4) is our string, so this line...
s.MagicNumber = unpack('i', (p.read(4)))
...gets our four bytes, interprets that as an integer, and passes the result to s.MagicNumber. A big caveat that I missed while writing this that caused a great deal of confusing is that it doesn't ACTUALLY pass JUST the integer. It passes a Python data type called a tuple with the integer I wanted as the first element of that tuple. Tuples (and other Python data types) work a lot like arrays in other languages - but more on that in a second.
The next line does pretty much the same thing...
s.Version = unpack('i', (p.read(4)))
Ok cool, we have now read two integers from the file and stored them in some variables. This next part is tricky and caused a lot of wailing and gnashing of teeth on my part. The struct documentation told me that "i" is the format character for integers, and "s" is the format character for character arrays (strings). Since the next 128 bytes of the file is a row of 128 characters (a string) I figured I could just replace the "i" with an "s" and then do p.read(128). This was incorrect. After a lot of pondering over error messages I carefully read through the struct module documentation and found that you have to precede the "s" with the number of characters to be read, like "128s". So that resulted in this line...
s.Comment = unpack('128s', (p.read(128)))
...and all was well.
Remember I said that unpack() returns a tuple, and in our case the first element of that tuple is that actual integer or character array we asked for from the file? Getting the first element out of a tuple is a lot like getting the first element out of a C array. If I have a tuple called MyTuple I can get the first element by asking for MyTuple[0]. So the print lines...
print('Magic Number: %s') % hex(s.MagicNumber[0])
print('Version: %d') % s.Version[0]
print('Comment: %s') % s.Comment[0]
...do exactly that. Oh - the first line says hex(s.MagicNumber[0]) because I want the integer returned to be printed out as a hexadecimal number.
All said and done that dozen lines of code took about an hour, which isn't bad considering I started out with only a superficial knowledge of how to read bytes. Hopefully the next step of reading the more important data from the file won't be so traumatic now.
Monday, February 6, 2012
First useful OOP
I finally made a functional, useful class.
I've made functional classes before, but they were only for show. This is the first time I've used OOP that actually makes programming the rest of the application easier and more organized. I'm not saying I'm a believer in OOP for the sake of OOP, but it works for me here.
Creating a new instance of this class is easy - you have to pass it a legit .csv file (no checks yet, those are coming) and on creation it chucks the data in the .csv to a list, where each list element is a type dict with key/values that match the columns/values per row in the .csv. This alone took me for freaking ever to make work because it took me for freaking ever to get my head around these Python types.
Almost every method in the Cases class is about whittling down the internally stored list of cases. Calling CasesBySalesman(salesman) alters the internally stored list to just those by a particular salesman.
I labored heavily over how to do this in the most efficient way possible. The first incarnation of this class had each method return a new list, leaving the original untouched. This, I felt, left too much work to the program that would be using this class to handle. My knowledge of the "spirit" of OOP is limited since my experience is limited, but my favorite definition so far of a class is "data, and methods to perform actions on that data", so I went with that. There is a convenient reset method to go back to baseline if necessary.
So, in the eventual program that will use this class it would be as simple as:
A = Cases(file.csv)
A.CasesBySalesman("Bob")
A.OpenCases()
And A.caselist would be a list of dicts with the open cases for Bob. This seems very straightforward. My first pass mentioned above would have involved something like:
A = Cases(file.csv)
allcases = A.AllCases()
casesbybob = A.CasesBySalesman(allcases, "Bob")
casesbybobopen = A.OpenCases(casesbybobopen)
So yea, too many variables, and here I've reduced my Cases class to just a fancy holder of functions, instead of encapsulated methods to perform actions on internal data.
I think I made the right choice, and I'm quite happy with it.
EDIT: There is a copy/paste problem in the code above, but it's not important.
I've made functional classes before, but they were only for show. This is the first time I've used OOP that actually makes programming the rest of the application easier and more organized. I'm not saying I'm a believer in OOP for the sake of OOP, but it works for me here.
Creating a new instance of this class is easy - you have to pass it a legit .csv file (no checks yet, those are coming) and on creation it chucks the data in the .csv to a list, where each list element is a type dict with key/values that match the columns/values per row in the .csv. This alone took me for freaking ever to make work because it took me for freaking ever to get my head around these Python types.
Almost every method in the Cases class is about whittling down the internally stored list of cases. Calling CasesBySalesman(salesman) alters the internally stored list to just those by a particular salesman.
I labored heavily over how to do this in the most efficient way possible. The first incarnation of this class had each method return a new list, leaving the original untouched. This, I felt, left too much work to the program that would be using this class to handle. My knowledge of the "spirit" of OOP is limited since my experience is limited, but my favorite definition so far of a class is "data, and methods to perform actions on that data", so I went with that. There is a convenient reset method to go back to baseline if necessary.
So, in the eventual program that will use this class it would be as simple as:
A = Cases(file.csv)
A.CasesBySalesman("Bob")
A.OpenCases()
And A.caselist would be a list of dicts with the open cases for Bob. This seems very straightforward. My first pass mentioned above would have involved something like:
A = Cases(file.csv)
allcases = A.AllCases()
casesbybob = A.CasesBySalesman(allcases, "Bob")
casesbybobopen = A.OpenCases(casesbybobopen)
So yea, too many variables, and here I've reduced my Cases class to just a fancy holder of functions, instead of encapsulated methods to perform actions on internal data.
I think I made the right choice, and I'm quite happy with it.
EDIT: There is a copy/paste problem in the code above, but it's not important.
Clever way of reading data into a dict type
https://github.com/breuderink/eegtools/blob/master/eegtools/io/edfplus.py
I like what's in the edf_header() function. I'm going to experiment with doing that.
Every time I noodle through GitHub I learn something new.
EDIT: The BaseEDFReader class has some justification for something I had to do to make something work - you pass the class init method a file and then it's assigning that file name to a self variable. I was struggling with why it was necessary for my stuff to work so this is evidence it's a thing you're supposed to do... for some reason.
I like what's in the edf_header() function. I'm going to experiment with doing that.
Every time I noodle through GitHub I learn something new.
EDIT: The BaseEDFReader class has some justification for something I had to do to make something work - you pass the class init method a file and then it's assigning that file name to a self variable. I was struggling with why it was necessary for my stuff to work so this is evidence it's a thing you're supposed to do... for some reason.
Friday, February 3, 2012
Push
I cleaned up my GitHub account and made a repository for my hacked together but very functional security camera program.
https://github.com/cheydrick/Security-Camera
I'll be making a few changes to it soon, and I'd like to take this opportunity to get to know Git (and GitHub) better. The first change is to make it more camera and save location agnostic. Those options should be set via command line. Even better I'd like it to auto-locate a local Dropbox folder as a default if no explicit save location is made.
I got a new computer at work so I took the time to proper set up a Python development environment using Eclipse and the PyDev plugin. I'm shuffling my old support case reporting code into a more organized structure. One big change is that I'm trying to use proper classes instead of a big list of functions. Now the big list of functions are a big list of class methods, so maybe I can hang out with the cool OOP kids now, I dunno.
The new Python books are coming in handy. I'm not reading them from start to finish - just using them as a reference.
I feel super bad about neglecting C so far this year. My compromise is that I want to revisit some experiments I ran last summer where I compiled a library in C that I could call from Python. I did the usual "Hello World" stuff, but I want to explore how to create dynamically allocated arrays of stuff in C in a way that Python can then see that data.
I left my C learning progress at a good stopping point. Getting my head around OOP in Python first should help when I revisit Objective-C. Uh, Obj-C and I got in a fight and that's why I walked away from it to cool off. That's a whole different story.
https://github.com/cheydrick/Security-Camera
I'll be making a few changes to it soon, and I'd like to take this opportunity to get to know Git (and GitHub) better. The first change is to make it more camera and save location agnostic. Those options should be set via command line. Even better I'd like it to auto-locate a local Dropbox folder as a default if no explicit save location is made.
I got a new computer at work so I took the time to proper set up a Python development environment using Eclipse and the PyDev plugin. I'm shuffling my old support case reporting code into a more organized structure. One big change is that I'm trying to use proper classes instead of a big list of functions. Now the big list of functions are a big list of class methods, so maybe I can hang out with the cool OOP kids now, I dunno.
The new Python books are coming in handy. I'm not reading them from start to finish - just using them as a reference.
I feel super bad about neglecting C so far this year. My compromise is that I want to revisit some experiments I ran last summer where I compiled a library in C that I could call from Python. I did the usual "Hello World" stuff, but I want to explore how to create dynamically allocated arrays of stuff in C in a way that Python can then see that data.
I left my C learning progress at a good stopping point. Getting my head around OOP in Python first should help when I revisit Objective-C. Uh, Obj-C and I got in a fight and that's why I walked away from it to cool off. That's a whole different story.
Saturday, January 28, 2012
clever
I've been experimenting with generating HTML for reports. It's pretty easy to do - writing a text file is more or less trivial in Python. Something I had struggled with is having large amounts of HTML text with placeholder variables. It gets unwieldy if you want to make little edits. I ran across this in the Python online documentation:
http://docs.python.org/howto/webservers.html#templates
I had been doing this in my code:
myvariable = "here"
htmltext = "imagine this is long html %s" % myvariable
which would make htmltext be "imagine this is long html here".
The issue is that my HTML is often super long (tables) and making small edits and making sure my variables are in line is annoying. The way they did this in the link is clever.
myvariable = "here"
htmltext = "imagine this is long html %s"
result = htmltext % myvariable
Now I can separate things out for readability. I should read the documentation more often!
http://docs.python.org/howto/webservers.html#templates
I had been doing this in my code:
myvariable = "here"
htmltext = "imagine this is long html %s" % myvariable
which would make htmltext be "imagine this is long html here".
The issue is that my HTML is often super long (tables) and making small edits and making sure my variables are in line is annoying. The way they did this in the link is clever.
myvariable = "here"
htmltext = "imagine this is long html %s"
result = htmltext % myvariable
Now I can separate things out for readability. I should read the documentation more often!
Tuesday, January 17, 2012
Python types are killing me
I spent probably two hours to get to this point:
All I wanted to do was import a .csv file as a dict type (values accessible by keys) and then be able to selectively choose which ones to do work on.
That didn't make sense, let's see if I can better explain it.
My data is a spreadsheet exported to .csv. Each row is a set of data with different things I need record of, like a date, name, notes, etc. Each column has a title, and DictReader sees this and makes those titles the keys.
So, if my .csv file looks like this
name, age
chris, 29
bob, 42
the dicts look like:
{'name':'chris', 'age':29}
{'name':'bob','age':42}
So the lets say I have a lot of these records and only want to do something with the people that have ages of 29. The above code will do that for me (just replace "print row" with whatever I really want to do).
It took me forever to get to this point because I'm still not used to handling data in Python. I thought that "reader" was a 2d array of dicts, but it's not. I have to by "Pythony" about things.
Dicts, lists, and tuples. I'm having a hard time getting my head around when to use each. Lets say I had a whole lot of data with lots of ages and I wanted to shuttle all the people of a certain age into their own variable for handling. What type is this variable? Is it a list of dicts? Is it something more akin what "reader" is? Is "reader" that csv.DictReader dumped out a list of dicts? The Python console says no - it's an instance of something. If it's not a data type then how am I able to iterate thought it with "for row in reader"?
Every time I jump into Python I wind up coming out with more questions than answers. I have trouble with Python that I never have with C. I will concede that when I do realize how to do something that it's fairly straightforward and only a few lines of code. That's nice. I might need to just surrender the need to know exactly what's going on and hope that this ignorance doesn't cause a massive bug that I can't track down due to not knowing the internals well enough.
All I wanted to do was import a .csv file as a dict type (values accessible by keys) and then be able to selectively choose which ones to do work on.
That didn't make sense, let's see if I can better explain it.
My data is a spreadsheet exported to .csv. Each row is a set of data with different things I need record of, like a date, name, notes, etc. Each column has a title, and DictReader sees this and makes those titles the keys.
So, if my .csv file looks like this
name, age
chris, 29
bob, 42
the dicts look like:
{'name':'chris', 'age':29}
{'name':'bob','age':42}
So the lets say I have a lot of these records and only want to do something with the people that have ages of 29. The above code will do that for me (just replace "print row" with whatever I really want to do).
It took me forever to get to this point because I'm still not used to handling data in Python. I thought that "reader" was a 2d array of dicts, but it's not. I have to by "Pythony" about things.
Dicts, lists, and tuples. I'm having a hard time getting my head around when to use each. Lets say I had a whole lot of data with lots of ages and I wanted to shuttle all the people of a certain age into their own variable for handling. What type is this variable? Is it a list of dicts? Is it something more akin what "reader" is? Is "reader" that csv.DictReader dumped out a list of dicts? The Python console says no - it's an instance of something. If it's not a data type then how am I able to iterate thought it with "for row in reader"?
Every time I jump into Python I wind up coming out with more questions than answers. I have trouble with Python that I never have with C. I will concede that when I do realize how to do something that it's fairly straightforward and only a few lines of code. That's nice. I might need to just surrender the need to know exactly what's going on and hope that this ignorance doesn't cause a massive bug that I can't track down due to not knowing the internals well enough.
Wednesday, January 11, 2012
Python CSV module DictReader
I'm tossing this link here as a reminder to take a look at it later.
http://www.doughellmann.com/PyMOTW/csv/
One of the reasons I stopped casually learning Python is because the documentation is incomprehensible to me. I wrote about this once before.
I'm hitting a problem at work that plagued me last year, and being able to pick stuff out of a .csv file (or an .xlsx file) would be really nice.
http://www.doughellmann.com/PyMOTW/csv/
One of the reasons I stopped casually learning Python is because the documentation is incomprehensible to me. I wrote about this once before.
I'm hitting a problem at work that plagued me last year, and being able to pick stuff out of a .csv file (or an .xlsx file) would be really nice.
Tuesday, December 13, 2011
Looking back at the security camera program
The Python+OpenCV program I wrote last summer is pretty handy.
http://chrislearnsc.blogspot.com/2011/03/added-timing.html
I use a modified version of that to take a picture every time I boot my laptop.
If I can find a way to get webcam images without using OpenCV I'd like to flesh the program out a bit and maybe add more options (command line or GUI with PyGTK). It's necessary to get away from OpenCV because it's serious overkill for just grabbing webcam images. Also, it's horrifying to install - it took me weeks to get it to work on my laptop and if it ever broke I wouldn't know where to start. I think that there are handy ways of grabbing webcam frames in Linux, but I don't know about OS X or Windows.
http://chrislearnsc.blogspot.com/2011/03/added-timing.html
I use a modified version of that to take a picture every time I boot my laptop.
If I can find a way to get webcam images without using OpenCV I'd like to flesh the program out a bit and maybe add more options (command line or GUI with PyGTK). It's necessary to get away from OpenCV because it's serious overkill for just grabbing webcam images. Also, it's horrifying to install - it took me weeks to get it to work on my laptop and if it ever broke I wouldn't know where to start. I think that there are handy ways of grabbing webcam frames in Linux, but I don't know about OS X or Windows.
Friday, August 5, 2011
The most frustrating program I've ever written
I think it's hard for anyone to take data in one format and get it into another to perform calculations. It's double hard when the language fights you a bit. I did everything I could to keep things "Pythony" but I'm still drastically unfamiliar with the language. I have a horrible suspicion that someone familiar with the language could do this in three lines of code.
Basically what the program does is this:
1) Read in a .csv file such that every row has its columns separated as individual elements in an array (Python list). Basically it makes a 2d array. List. Whatever
2) Remove the first row because it's the column names
3) Go through every row and copy over the ones that have something in the open date and close date columns. This makes a new list.
4) Take the new list and extract for each row the first and second column
5) Convert these extracted elements into a 3 element list
6) convert THAT list into a list of integers
7) convert that list of integers into a date and use it to calculate days between the close date and the open date
8) emit heavy sobs when it takes all damn evening to write, rewrite, write special simplified functions, rewrite again, insert a ton of print statements to get a handle on what's actually happening, finally figure out how to manipulate lists like you want, and then clean up any misc bugs and finally at your last nerve see it work.
I'm frustrated that I still don't know when to use classes vs a bunch of functions.
I'm frustrated that scope is horrifyingly ambiguous.
I'm frustrated that in a week I won't be able to read this code and make sense of it.
I'm happy that I tackled the hardest but most meaningful part of the analysis I want to do.
I can't balk at the fact it only took me a week to get well versed enough to first get through enough of LPTHW to comprehend the language and knock out the program. I started working on it this morning. I think I spent 3.5 hours on this total? Not bad, but it was an infuriating 3.5 hours. That time isn't counting when I walked away in frustration.
It's a start
This gets me to the bare minimum of getting the .csv file into a form I can work with. I'm not certain that this is the "pythony" way of doing things, but I know what to do with an array.
Thursday, August 4, 2011
Just to really beat it in...
Ok, here are some simple examples to drive the point home.
First is a script that has a variable assigned and a function called can see this variable.
The output of this script is:
Ok, this makes sense. All well and good.
Here is a script that has a variable assigned, and a function called can see it BUT when it tries to modify it I get an error.
The output:
If, however, I simply first inside the function state "global im_outside" it becomes allowed to modify the variable.
Alright, let us see a C example:
Output is:
And altering the function to modify the variable:
And I get the result I wanted:
I am certain I understand how scope works in C. It's pretty straightforward and a lot of the difficulty with understanding passing values/references to functions is a consequence of that simple straightforwardness. I think what this means is that I don't understand scope in Python. I just think if a function can "see" a variable it should also be able to modify that variable. Look, I get it that maybe having the "global" description happen elsewhere is a good idea because then you can let SOME functions modify the var but not others, but man is it not intuitive.
First is a script that has a variable assigned and a function called can see this variable.
The output of this script is:
Here is a variable I can see: 42
Here is an outside variable as seen from a function: 42
Ok, this makes sense. All well and good.
Here is a script that has a variable assigned, and a function called can see it BUT when it tries to modify it I get an error.
The output:
Here is a variable I can see: 42
Traceback (most recent call last):
File "scopetest2.py", line 10, in
afunction()
File "scopetest2.py", line 4, in afunction
print "Here is an outside variable as seen from a function: %d" % im_outside
UnboundLocalError: local variable 'im_outside' referenced before assignment
If, however, I simply first inside the function state "global im_outside" it becomes allowed to modify the variable.
Alright, let us see a C example:
Output is:
Here is a variable I can see: 42
Here is an outside variable as seen from a function 42
And altering the function to modify the variable:
And I get the result I wanted:
Here is a variable I can see: 42
Here is an outside variable as seen from a function 42
But now I'm going to modify it
And here it is: 27
I am certain I understand how scope works in C. It's pretty straightforward and a lot of the difficulty with understanding passing values/references to functions is a consequence of that simple straightforwardness. I think what this means is that I don't understand scope in Python. I just think if a function can "see" a variable it should also be able to modify that variable. Look, I get it that maybe having the "global" description happen elsewhere is a good idea because then you can let SOME functions modify the var but not others, but man is it not intuitive.
scumbag python
Ok wow.
So, you have to say:
global wumpus_room
BUT you can't declare it as global AND assign it at the same time.
Oh, and the kicker? You're after-the-fact declaring at as a global variable INSIDE the function you want to modify it in!
So:
I guess by "declaring" inside the function that it needs to be on the lookout for a outside-declared instance of wumpus_room that this makes it ok to alter. This does NOT AT ALL explain why I can see the initial value of the variable as defined outside of the function.
Is "global" only necessary to MODIFY a variable outside of the scope... but not read the value? Doesn't that make the concept of "scope" twisted?
EDIT: Here's the site I got from my google searching on the subject http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/
So, you have to say:
global wumpus_room
BUT you can't declare it as global AND assign it at the same time.
Oh, and the kicker? You're after-the-fact declaring at as a global variable INSIDE the function you want to modify it in!
So:
I guess by "declaring" inside the function that it needs to be on the lookout for a outside-declared instance of wumpus_room that this makes it ok to alter. This does NOT AT ALL explain why I can see the initial value of the variable as defined outside of the function.
Is "global" only necessary to MODIFY a variable outside of the scope... but not read the value? Doesn't that make the concept of "scope" twisted?
EDIT: Here's the site I got from my google searching on the subject http://www.saltycrane.com/blog/2008/01/python-variable-scope-notes/
Python woes
Woof, I don't understand variable scope in Python.
I have what I thought was a global variable called "wumpus_room" that is a random whole number between (and including) 0 to 3. The script is borking at the fact that I have a line that could alter this variable inside of a function. If I comment out the block starting with
elif choice.lower() == "shoot north":
then there is no complaint.
This would not be confusing if it was crabbing about trying to alter a variable out of scope, but it gives a cryptic error:
UnboundLocalError: local variable 'wumpus_room' referenced before assignment
See.... I'd BELIEVE that if not for the fact I can comment out that reassignment line and everything works fine - this tells me the variable is indeed getting assigned!
How the heck do I declare a global variable and then edit that variable if necessary?!
Wednesday, August 3, 2011
LPTHW Exercise 35 and 36
LPTHW exercise 35 brought home a lot of function and control structure concepts with an example of a small text adventure game.
http://learnpythonthehardway.org/book/ex35.html
Exercise 36 asks that you take what you learned and make one of your own. I'm doing basically a five room "hunt the wumpus" game. The structure is basically every room has its own function, and each room asks which way you want to go or where you want to fire your arrow which then either calls the respective room's function, or the fire arrow function. It's not a "proper" way of organizing data for a game but it's just to drive home functions and control structures.
This really brings me back to middle school doing some QBasic programming along the same lines. I have a really strong grasp of control structures because of all the nested if-loops and while-loops of the text adventure games my friends and I used to make together. It sucks that ASCII graphics is now really hard to do since terminal interactivity is now considered an anachronism (among most folks, anyways).
http://learnpythonthehardway.org/book/ex35.html
Exercise 36 asks that you take what you learned and make one of your own. I'm doing basically a five room "hunt the wumpus" game. The structure is basically every room has its own function, and each room asks which way you want to go or where you want to fire your arrow which then either calls the respective room's function, or the fire arrow function. It's not a "proper" way of organizing data for a game but it's just to drive home functions and control structures.
This really brings me back to middle school doing some QBasic programming along the same lines. I have a really strong grasp of control structures because of all the nested if-loops and while-loops of the text adventure games my friends and I used to make together. It sucks that ASCII graphics is now really hard to do since terminal interactivity is now considered an anachronism (among most folks, anyways).
The Python documentation makes no sense to me
Here's how a Python class function (method?) prototype is presented:
class datetime.datetime(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])
I read this as tzinfo is an argument of microsecond which is an argument of second which is an argument of minute which is an argument of hour which is an argument of day. But this isn't the case. It's just a list of arguments that can be passed separated by a comma. So... why the brackets?!
Furthermore in THIS class function the non-bracketed variables are stated as required, and the bracketed ones are optional. So I say to myself "Ah, that's how they define optional and non-optional arguments. However, here:
class datetime.time(hour[, minute[, second[, microsecond[, tzinfo]]]])
the documentation says that all arguments are optional, which blows away that theory of operation.
So yea, the biggest hindrance to getting to the next level in Python is that I can't read the documentation.
class datetime.datetime(year, month, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]])
I read this as tzinfo is an argument of microsecond which is an argument of second which is an argument of minute which is an argument of hour which is an argument of day. But this isn't the case. It's just a list of arguments that can be passed separated by a comma. So... why the brackets?!
Furthermore in THIS class function the non-bracketed variables are stated as required, and the bracketed ones are optional. So I say to myself "Ah, that's how they define optional and non-optional arguments. However, here:
class datetime.time(hour[, minute[, second[, microsecond[, tzinfo]]]])
the documentation says that all arguments are optional, which blows away that theory of operation.
So yea, the biggest hindrance to getting to the next level in Python is that I can't read the documentation.
Tuesday, August 2, 2011
even more progress
I'm on exercise 27 now in LPTHW. I think I've spent a total of four or five hours on it. It really helps already being familiar with C since I don't have any issues comprehending the "advanced" stuff so far (functions, return values, taking arguments, importing functions from other files). I'm still weak on some of the formatting like %d and %s and %r in the print statements, but basically it's numbers, strings, and a different way of formatting string statements.
a little progress
I got through the first five exercises in LPTHW, which isn't saying much since it's just typing out the examples (no copy/paste is the rule in this book) and it only took about 45 minutes (including setting up the environment). So far It's all just printing and some light variable usage.
Here's where I stopped: http://learnpythonthehardway.org/book/ex5.html
Here's where I stopped: http://learnpythonthehardway.org/book/ex5.html
Wednesday, June 29, 2011
Using a shared library written in C with Python
I'm trying to combine some C and Python. Did some "light" reading on the ctypes module in Python.
There are several ways of using C libraries in Python. Ctypes, SWIG, Cython, and plain making a Python module in C. Ctypes seemed the most straightforward.
Ok, to start with I needed a library. I jumped into Ubuntu and started a new shared library project in CodeBlocks and did the following:
There are several ways of using C libraries in Python. Ctypes, SWIG, Cython, and plain making a Python module in C. Ctypes seemed the most straightforward.
Ok, to start with I needed a library. I jumped into Ubuntu and started a new shared library project in CodeBlocks and did the following:
This compiles to a .so file. I named the project sayhello so it compiled libsayhello.so. I put this file in /user/lib.
Alrighty so I have my library. Time to get into Python. I don't have any Python IDE so I just use the terminal. I want to use Python to call my sayhello() function.
And there you have it - a VERY simple example of calling a C function in Python.
There is a lot about shared libraries I don't understand. I have a superficial knowledge of what's happening behind the scenes (and I know what the benefits of using dynamic link libraries are). I keep reading things about "exporting" or "importing" functions but I'm not sure what that means, and I don't understand some of the stuff I see in Windows .dll source code.
Aaaanyway. I've been up since 6am on this and I am done thinking about this for today.
Sunday, March 20, 2011
added timing
Added some code to deal with timed capture. It works but I'm wondering if it's the best way to handle detecting elapsed time. That test loop is a "run as fast as possible" thing and I'm not sure how much processor it's using (although I won't be using the PC while it's running once it's done).
I'm pretty happy with this.
I'm furious that I still can't get the CV module to work in OS X. There will be a very detailed post about that soon.
EDIT: It's worth mentioning that setting the resolution isn't working. I think I need to install the Logitech drivers that may or may not work with Win7.
Subscribe to:
Posts (Atom)