Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

I'm trying to write some function to upload files via FTP. My "problem" is that it feels like I'm kludging my status updates with percent done, KB's uploaded, and KB per second. The reason I've done it as I've done it is that I can't think of a better way to pass data back and forth between each time the callback is called.

In short, I hate screwing with global variables like this, is there a better way?

code:
import os
import ftplib
import time

def upload(ftp, f):
    #initialize some stuff since callbacks can't have arguments
    global blocksize
    blocksize = 8192
    global data_tran
    data_tran = 0
    global last_KBs_update
    last_KBs_update = 0
    global last_sec_tran
    last_sec_tran = 0
    
    ext = os.path.splitext(f)[1]

    if ext in (".txt", ".htm", ".html"):
        ftp.storlines("STOR " + f, open(f))
    else:
        file_start_time =time.time()
        ftp.storbinary("STOR " + f, open(f, "rb"), blocksize, print_callback)
        file_end_time = time.time()
        print

def print_callback(block):
    #variables that need to be persistent between each callback
    global data_tran
    global last_KBs_update
    global last_sec_tran
    global KBs
    
    data_tran += len(block) #Total data transferred
    KB_tran = data_tran / 1024 #In KB
    KB_filesize = filesize / 1024 #Filesize in KB
    per_done = (float(data_tran) / float(filesize)) * 100 #Percent transferred
    last_sec_tran += len(block)/1024 #Data transferred since updating KB/s

    if time.time() - last_KBs_update > 1: #Update KB/s every ~1 sec
        elap_time = time.time() - last_KBs_update #Exact time since update
        KBs = last_sec_tran/elap_time 
        last_KBs_update = time.time()
        last_sec_tran = 0
    
    print "%.2f%%  (%iKB of %iKB) (%.2f KB/s)" % (per_done, KB_tran,
                                                KB_filesize, KBs), '\r', 

filesize = os.path.getsize(YOUR_FILE)
f = ftplib.FTP('')
f.connect(IP, PORT)
f.login(USERNAME, PASSWORD)
f.cwd(FTP_DIR)
upload(f, YOURFILE)

Adbot
ADBOT LOVES YOU

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Two related questions:

1. Can someone please compile MySQLdb for Python 2.6 on Windows? On sourceforge a couple of random people have attempted it, but neither of their packages work for me:

code:
Traceback (most recent call last):
  File "<pyshell#0>", line 1, in <module>
    import MySQLdb
  File "C:\Python26\lib\site-packages\mysql_python-1.2.2-py2.5-win32.egg\MySQLdb\__init__.py", line 19, in <module>
  File "C:\Python26\lib\site-packages\mysql_python-1.2.2-py2.5-win32.egg\_mysql.py", line 7, in <module>
  File "C:\Python26\lib\site-packages\mysql_python-1.2.2-py2.5-win32.egg\_mysql.py", line 6, in __bootstrap__
ImportError: DLL load failed: The specified module could not be found.
2. How come Python doesn't come with a MySQL module? It seems like this would be a pretty important feature...

Thermopyle fucked around with this message at 20:03 on Mar 1, 2009

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Janin posted:

Despite all the hype pip receives, it fails to perform the two tasks I need a package manager to do. If all I had to worry about was pure-python tarballs installed on POSIX systems, there would be no need for any tool but "cp".

Yes, I really wanted to use pip, but the lack of Windows support turned me off. I wish it supported Windows not only for my current projects, but I want pip to spread far and wide, and not supporting Windows will hinder that. :(

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Funnehman posted:

I started learning python yesterday, and bumped in to some pretty expansive python IRC bot guides on http://www.devshed.com and had tons of fun with that all day. Only problem now is, I don't know what I want to(or what I'd even be capable of) outside of that. Lots of people say that's the hardest part of learning to program, which sucks because when I'm trying to make stuff and have ideas I'm having a blast, but after screwing around making various IRC bots to do different things all day I don't know where to go next.. This is probably a really stupid question, but does anybody have maybe a suggestion or two on fairly beginner friendly projects to work on?

I think I just started learning the wrong way, and I know barely anything about the offline side of python, and just started doing IRC poo poo after leaning basic syntax.

When I started learning python 6 months ago, I used it to solve little problems that I run in to every day.

For example, I had a directory with 10,000+ images that I wanted to sort in to different directories by resolution, so I wrote a script to do that. Another thing was that I wanted to graph the different stats reported by my cable modem's web interface, so I wrote a python script to fetch that stuff into a csv every five minutes.

Basically, think about things you do every day and figure out if there's a way to write a script to do it better.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Funnehman posted:

Yeah I have a few things like that, I do wish I had more though, I just can't wrap my head around OOP and poo poo, up until an hour or two ago, I had no clue how to call the functions in module files, and poo poo like that.

The worst part for me, I think... Is I'll try to think of a project, or hear one taht sounds cool, and I'll think about how I could do it for a while.. Then I'll be like nah I don't just wanna lay down the code, everyones doing OOP now, I'd look like a scrub!

Actually, I'm kind of in the same boat. I'll learn something only if I have a reason to, and I haven't really had a reason to use classes or any OOP stuff. I haven't really done anything where I could see a reason to use anything other than regular ole' functions.

I have wrote a little something that I've released into the wild, though! I've got to do a little hacking on it, because I didn't realize at the time that python now includes the json module...

Thermopyle fucked around with this message at 22:12 on May 2, 2009

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Sylink posted:

Can someone explain parsing with elementtree to me, it makes no sense and the effbot stuff seems to all be about making xml, I just want to get information.

Like if I have an element <title>, how do I get the actual content between the tags?

I have no experience with elementtree, but you may want to look at BeautifulSoup.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

I'm kind of a beginner, and this is my story.

I don't get classes. Every time I start a project I think: "Damnit, I'm going to learn what these are good for now." Except, once I start, I end up not using them because I'm comfortable with the way I do things. Basically I worked all the way through Think Python up to the Files chapter. When I got to "Classes and objects" I started reading and then thought "I don't need this poo poo." and then went out and wrote a bunch of scripts.

I want to learn them, but similar to how many people need a project to learn to program, I need a reason to use them before I'll learn them.

Basically, I want someone to talk me into thinking they're useful for something.

Thermopyle fucked around with this message at 16:33 on May 25, 2009

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

jupo posted:

From what you've said it's safe to assume that the kind of things you're programming are fairly small in scale. For simple scripts that are smaller than a few hundred lines of code the benefits of classes really aren't obvious. Once you start getting into some more meatier projects the benefits classes will provide in structuring your data in a modular way will become much more apparent.

Some OO zealots will apply classes to *everything* when really it's about using the right tool for the right job, classes aren't always the answer.

What might also be beneficial to your understand is trawling through the source code for the standard library and seeing how OO is applied to various tasks there.

This is true. Largest of my scripts are around 150 lines. Most of them are automation scripts like scraping something from a website and doing something with that, or organizing files, etc...

I guess I'll have to think of a "meatier" projects.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Mechanize is giving me fits.

Basically, it doesn't recognize that there are any forms on this page.

Here's some demonstration code:

code:
from mechanize import Browser

url = 'https://steamcommunity.com'

br = Browser()
br.open(url)

br.select_form(name="loginForm")
print br.form
br["steamAccountName"] = "ACCT"
br["steamPassword"] = "PASS"
response2 = br.submit()
print response2.read()
This results in:

code:
Traceback (most recent call last):
  File "C:\Users\Therms\Documents\programming\python\mechanize experiments\mech_
test.py", line 11, in <module>
    br.select_form(name="loginForm")
  File "build\bdist.win32\egg\mechanize\_mechanize.py", line 505, in select_form

  File "build\bdist.win32\egg\mechanize\_html.py", line 546, in __getattr__
  File "build\bdist.win32\egg\mechanize\_html.py", line 559, in forms
  File "build\bdist.win32\egg\mechanize\_html.py", line 228, in forms
mechanize._html.ParseError
This is on Windows with python2.6, but I get the same error on linux with python 2.5.

Other Browser methods will follow links on that page, but forms just won't work. I can get forms on other sites to work fine.

I'm trying to write a script that will invite to our Steam Group anyone who ranks above a certain rank on our Psychostats. This requires logging in and maintaining cookies and whatnot...thus the use of mechanize.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Sailor_Spoon posted:

I ran it on OSX, python2.6, mechanize 0.1.11 and got some weird poo poo. I just called br.open(), and then br.forms() and got:
code:
<type 'str'>: (<type 'exceptions.AttributeError'>, AttributeError("'ParseError' object has no attribute 'msg'",))
It's strange though, I tried loading the page in twill, which is really just a wrapper for mechanize, and it worked fine. Maybe that might work better for you?

This is odd.

I get the same errors I mention in my post on linux with python 2.5 and windows with python 2.6. Twill also gives me the same errors.

Guess I'll dig in to it more.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Centipeed posted:

What is the "accepted" way of implementing a simple substring search for plain text?

Is there something wrong with str.find()?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

bitprophet posted:

To ask a Python question: anyone know of any decent "CLI UI" (and not curses-based, I don't think) libraries for Python? I'm thinking of commonish stuff like progress bars, spinners, formatting data into columns, simple "choose option A B or C" menus, and so forth. (I could swear I saw a PyMOTW posting on that last one, but can't find it now. Maybe I should ask Doug...)

Yes, many of these tasks are relatively simple, but it's still annoying to try and reinvent the wheel and it feels like the sort of thing that someone would have written a lib for.

If this exists, it would be cool. I'm always writing progress bars and the like.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

His Neutralness posted:

How would I keep printing on the same line (just using the shell), like if I was printing the speed something was downloading at?

code:
import time
for i in range(20):
    print str(i) + '\r',
    time.sleep(1)
The '\r' returns to beginning of line and the ',' suppresses the new line.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Ok, I've decided to just make myself learn wtf classes are good for.

I'm designing a script to take entries from my google reader shared items rss feed and do various things with each item like post it to a Twitter feed, Facebook, post it on a forum, etc...

The problem is that classes seem kind of weird to me, and I'm having a hard time thinking about them with the right mind-set.

This is my current thinking about some classes to use:

  • A class for an item in the rss feed. Have various methods for doing the things I mentioned above.
  • A class for the rss feed. The constructor will take the url to the feed, fetch it, and create instances of the above class for each entry in the feed.

The second item I'm a little confused about. On the one hand it seems like I should make it a class because classes are cool, but on the other hand, I don't really see a reason for it to be a class as the things it does should only be done once each time my script is run.

Basically, I'm just looking for some ideas and thoughts about how people with experience would design such a project.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

acker posted:

Why not just have a function that takes the URL and returns a list of instances of the item class?

Basically because I'm a noob to OOP and didn't know if it was bad form to mix functions and classes in such a manner. Of course, now that I think about it, I use regular Python objects all the time...

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Mata posted:

I feel really stupid but I'm not really used to this language... how do you change parts of a string?

What I want to do is basically like: mystring[40] = 'i' at a few select places.
what's the best way to go about it? the whole string can get up to a few megabytes so ideally i wouldn't want to copy it around too much. Do i have to split it up then merge it again?

Strings in python are immutable. The best you can do is create a new string that is a variation on the original.

Maybe something like this:

code:
mystring = mystring[:39] + 'i' + mystring[41:]

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

TheMaskedUgly posted:

I'm new to python, but I've written a long program and it has an issue.
Basically it copies a template web page, and makes 10 copies of it with different first paragraphs. Because I'm new, this has ended up being a fairly long program. When I run it, it gets through each copy fine until it get to the last one. It only manages to copy the last page half way. If I swap the programming for the 9th and 10th copies, then the 9th only gets halfway, so I know its not the actual code that's the problem.
Is there a maximum length for a python program? That seems highly unlikely. (The code's a couple of hundred lines long max) Any ideas?

E: This was written in IDLE 2.6, by the by. Also, I've got a punctuation checker that only actually works if I open it and hit f5 in the IDLE editor, but not if I just double click on it, running it through command prompt. It's only 4 seconds of effort, but it still seems like that shouldn't be right?

Not enough info. Post the code. Also, a couple of hundred lines isn't long at all, so don't worry about that.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

HatfulOfHollow posted:

I can write a multi-threaded application with no problem but for some reason twisted just confuses the hell out of me. I think it's the layer of abstraction. Not seeing exactly what's going on behind the scenes makes it harder for me to understand.

I've noticed the same. It makes me feel dumb.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Ethereal posted:

Does anyone have recommendations for a good host with Python as a usable language? I'm planning on setting up a small-ish site and don't need that much bandwidth per month, just a good reliable provider.

I've had plenty of success with Dreamhost.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

As a fairly novice programmer who's beginning to write more complex pieces of code, I'd like more advanced programmers to look at my code and tell me how badly I've hosed up.

I've currently got a class I'm writing that takes a filename of a downloaded TV show and tries to parse out the episode and season number. It's about 100 lines long so far.

Is there a good site out there focusing on hooking up programmers who are willing to look at other people's code? Would someone here like to look at it and make some comments for me?

edit: Hell, i'll throw it up on pastebin and if someone wants to look they can just do it....

http://pastebin.com/ma24c43

sample use:

code:
file = r"Doctor Who 070 - 11x01-04 - The Time Warrior (complete).avi"

show = TV_Show(file)
print show.parse_name()

Thermopyle fucked around with this message at 22:13 on Sep 7, 2009

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

outlier posted:

Woah.

...lots of really useful feedback...

Thank you! Exactly the sort of information I was hoping for.

tef posted:

That and there is almost no reason to make it a class over a function that returns a string

You know, I started to write a function and then I decided I'm going to stop dicking around and make myself learn how the hell classes work. Besides, in the future I may expand this into a more full-featured program where I'd like to be able to query each bit of info. I was under the impression that a class would would facilitate that better.

Lurchington posted:

I've been fooling around with TV Show name parsing for a LONG time, and depending on how much you delve into it, you can see all my work at Keasby's google code repo.

Thanks, I'll look it over.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

RobotEmpire posted:

1. Should I just give up and install a Linux flavor if I really want to get back into teaching myself Python? (And how to code, in general)
2. How are GUIs created in Python? Or are they, even?
3. Is it hopeless to start coding at 30? I love reading over code, I love spending hours in Python (iPython :3:), and I know I like listening to my friends discuss development, though I can't contribute anything meaningful. Did I pretty much miss the boat by not being locked in my room at 15 and teaching myself to program then?

1. Python is great on Windows.
3. I decided to learn Python this summer. I'm 31, and while I'm no elite hacker dood, I haven't had any problems.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Janin posted:

And here's the biggest, worst problem: for 99% of Twisted, the documentation is insufficent to know in what ways the various procedures are manipulating the implicit, global, god-state. You're going to spend more time reading the Twisted codebase than your own code, because every abstraction they've implemented leaks like hell.


I wanted to use Twisted awhile back for some project. I'm pretty new to this whole programming thing, and after futzing around for a few hours I just gave up on Twisted because of the god-awful docs. So yea, Twisted documentation is pretty crappy.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

I'm writing some stuff that interacts with utorrent via it's Web API.

One of the things I do is create a dictionary of utorrent settings like this:

code:
utsettings['downloaddir'] = "C:\downloads"
I have a function like this:

code:
def change_setting(setting, value):
So when I want to change something I call it like this:

code:
change_setting('downloaddir', 'D:\new_download_dir')
It would be awesome if I could somehow automatically call change_setting() when I modify the dict utsettings. Possible? Stupid? Advice?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

ErIog posted:

Why don't you have your change_setting function submit the change, and then modify the dict with that information? I mean, if you're changing the setting yourself, then you're going to want your dict to keep track of it.

Yeah, this is actually what I do now.

It just seems like it would be more...I dont know..."objecty" and elegant if by modifying the dict I was actually modifying the setting.

This was more idle thought than something I've got to do...

jupo posted:

You can subclass dict and override its __setitem__ method that gets called every time you add/update a keyvalue pair:
code:
class Settings(dict):

	def __setitem__(self, key, value):

		# call change_setting() here
		dict.__setitem__(self, key, value)

settings = Settings()
settings["foo"] = "bar" # __setitem__ gets called here automatically

oooo. I get it, thanks!

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Ok, completely different question...

I'm starting on my first projects that I think will benefit from splitting into more than one file.

To start out with I'm taking a long-ish script I wrote and dividing it into several files. What's the best way to handle utility functions that are used both in my main file and in the modules that I import?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

From the python docs:
code:
class Error(Exception):
    """Base class for exceptions in this module."""
    pass

class InputError(Error):
    """Exception raised for errors in the input.

    Attributes:
        expression -- input expression in which the error occurred
        message -- explanation of the error
    """

    def __init__(self, expression, message):
        self.expression = expression
        self.message = message

class TransitionError(Error):
    """Raised when an operation attempts a state transition that's not
    allowed.

    Attributes:
        previous -- state at beginning of transition
        next -- attempted new state
        message -- explanation of why the specific transition is not allowed
    """

    def __init__(self, previous, next, message):
        self.previous = previous
        self.next = next
        self.message = message
Ok, so I'm new and still evolving my understanding of classes and error handling. What I don't understand here is what the point of the Error class is...it doesn't do anything.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Milde posted:

Error doesn't have any attributes or methods but it does inherit all of the attributes and methods from the Exception class. The other two classes have their own __init__ methods because they apparently need to deviate from their base classes.

I would imagine Exception itself doesn't do much of anything itself either. One important aspect of exceptions is they have a name - otherwise, how would you raise and catch them? They also have a hierarchy (through subclassing) that lets you be less specific or more specific about the kinds of exceptions you want to catch.

So, the classes themselves don't necessarily do a whole lot; it's the raise/try/except functionality that handles the interruption of code flow. If that still doesn't make sense, I'd try looking for some examples of how to use exceptions, maybe from a tutorial or some existing code.

Right, but I mean why create the Error class at all? Why not just have the InputError and TransitionError inherit directly from Exception?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

BeefofAges posted:

What would you do when you decide that all of your errors should have some common property? Would you go and edit each one individually?

I thought of that, but if that was the point of the example, it seems like the docs should havve actually included a common property instead of "pass". So I assumed that wasn't the point.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Objects with attributes composed of standard data types along with attributes that are other objects, how do I handle persistent storage?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

code:
>>> d['show1'] = show
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "C:\Python26\lib\shelve.py", line 132, in __setitem__
    p.dump(value)
cPickle.UnpickleableError: Cannot pickle <type '_sre.SRE_Match'> objects
>>>
So what do I do if my object also includes regex.match objects?

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Habnabit posted:

So I've long been sick of MySQLdb for being a horrible mysql driver as well as just being horribly written in general. Of course, there's also frequent questions on #python regarding either how horrible MySQLdb is or why the maintainer hasn't released any 2.6 binary packages for windows.

To solve all of this, I wrote my own mysql driver from scratch using Cython: oursql! It's still very much in-development and I haven't finished writing a comprehensive tutorial, but it works pretty well as far as I've tested. There's also a windows binary package for python 2.6!

It's a standard DB-API driver, so you can use it mostly the same way as MySQLdb previously. I haven't tested to see if you can easy_install it yet. Packages for the main package manager systems are being submitted as I figure out how to write them.

Hopefully there's some folks in this thread who are as tired of MySQLdb as I was and don't mind testing out a new driver.

Good for you! Awhile back I almost got to the point where I was going to teach myself how to do the same. Instead, I figured out how to compile MySQLdb for Windows myself (get it here if anyone needs it).

I'll be keeping an eye on your project, though.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Thought I'd post this here as esr wrote ForgePlucker in python. He's had a couple blog posts about the wisdom of scraping HTML with regex, and as always, the posts and the comments are entertaining.

http://esr.ibiblio.org/?p=1411

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

What's the right way to debug a function?

Specifically, I'm working on a script right now with a function that's giving me some problems. When it drops back to the interactive interpreter I'd like to explore the values of various variables that are local to the function, but we're not in the function anymore so those variables aren't accessible.

code:
def somefunc(wiggedywhack):
	stupid = []
	for i in range(10):
		awesome_broken_code
		stupid.append(i)

somefunc('cawk')

#awesome_broken_code breaks, how do I inspect 'stupid'

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Which is better?

code:
def save(obj):
    shelf[obj.name] = obj
or...
code:
class obj():
    def save(self):
        shelf[self.name] = self

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

tehk posted:

It depends on what shelf is, and how you are using it. If save is not manipulating its own object I would not make it a method of obj, however if it is some object relational thing then the second approach makes sense. You have a third option of adding save to a subclass of what ever type(dict) shelf is. That seems the least magical for when you are reading the code later.

Shelf is a shelve. I'm storing my object on disk.

Save isn't manipulating it's own object per se...it's storing the object in the shelve.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

HatfulOfHollow posted:

I'm confused why you would want to store the object in the shelf. It really doesn't make much sense to me.

That's how the shelve module works.

quote:

A “shelf” is a persistent, dictionary-like object. The difference with “dbm” databases is that the values (not the keys!) in a shelf can be essentially arbitrary Python objects — anything that the pickle module can handle. This includes most class instances, recursive data types, and objects containing lots of shared sub-objects. The keys are ordinary strings.

The question boils down to: Is it better to have a function insert an object into a shelf, or is it better to have an object put itself (via a method) on the shelf?

Thermopyle fucked around with this message at 23:57 on Nov 28, 2009

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

HatfulOfHollow posted:

No I mean, why do you need a save method? Why can't you just do

code:
shelve[name]=obj
wherever you need to update? It just seems kind of unnecessary.

It seems like it's the most maintainable. Say I want to switch to MySQL, or some fancy other method of persistence in the future.

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Plorkyeran posted:

Then you'll have to change __setitem__ instead of save.

Isn't it as wide as it is tall? I mean, the dict-like nature seen in "save" is just an artifact of using shelve.

Forget about shelve. Pretend the contents of "save" is code for writing results to a MySQL database.

The question is more about coding style and less about shelve.

Adbot
ADBOT LOVES YOU

Thermopyle
Jul 1, 2003

...the stupid are cocksure while the intelligent are full of doubt. —Bertrand Russell

Plorkyeran posted:

The class obj(): def save(self): shelf[self.name] = self version actually does do something interesting, as it gives objects control over how they're persisted. However, if def save(obj): shelf[obj.name] = obj was ever actually useful, then it should actually be class obj(): def save(self): save(self.name, self), as having to modify every class that can be persisted when you change persistence layers is almost as bad as having to change every place where an object is saved.

In Stack Overflow style, I mark this as the accepted answer. :D

  • Locked thread