Python's "only one way to do it" philosophy isn't good?

A

Adam Pletcher

Does anyone have Python code for writing Targa (TGA) image files?
Ideally, with options for bit-depth/alpha channel, and RLE compression,
but I'm probably reaching there.

PIL is read-only for TGAs, unfortunately, and so far I'm striking out on
Google.
Thanks.
 
S

Steve Holden

Douglas said:
I apologise for this irrelevant interruption to the conversation, but
this isn't the first time you've written that.

The word "chaque" is not a pronoun.

http://grammaire.reverso.net/index_alpha/Fiches/Fiche220.htm

Right, he probably means "Chaqu'un à son gout" (roughly, each to his own
taste).

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
--------------- Asciimercial ------------------
Get on the web: Blog, lens and tag the Internet
Many services currently offer free registration
----------- Thank You for Reading -------------
 
S

Steve Holden

Douglas said:
Actually, it's "chacun". And the "à" may precede the "chacun".

|>oug

http://everything2.com/?node_id=388997 is clearly not authoritative, as
the "literal translation" about which it speaks is far from literal (it
mistakes the preposition "à" (to) for "a", the present tense of the verb
to have. I suppose the literal translation is "Each one to his own
taste". It does offer some support to my theory, however. So I'll quote
the damned thing anyway.

"chacun" is an elision of the two words "Chaque" (each) and "un" (one),
and use of those two words is at least equally correct, though where it
stands in modern usage I must confess I have no idea. The word order you
suggest would be less likely to be used by a peasant than a lawyer.
Being a peasant, I naturally used the other wording.

IANA linguist-ical-ly y'rs - steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
--------------- Asciimercial ------------------
Get on the web: Blog, lens and tag the Internet
Many services currently offer free registration
----------- Thank You for Reading -------------
 
D

Douglas Alan

"chacun" is an elision of the two words "Chaque" (each) and "un"
(one), and use of those two words is at least equally correct, though
where it stands in modern usage I must confess I have no idea.

Google can answer that: 158,000 hits for "chaqu'un", 57 million for
"chacun".

|>oug
 
D

Douglas Alan

Chris Mellon said:
Obviously. But theres nothing about the with statement that's
different than using smart pointers in this regard.

Sure there is -- smart pointers handle many sorts of situations, while
"with" only handles the case where the lifetime of the object
corresponds to the scope.
I question the relevance of your experience, then.

Gee, thanks.
Refcounting is fine for memory, but as you mention below, memory is
only one kind of resource and refcounting is not necessarily the
best technique for all resources.

I never said that it is the best technique for *all* resources. Just
the most typical ones.
You still don't have to manually close files. But you cannot, and
never could, rely on them being closed at a given time unless you
did so.

You could for most intents and purposes.
If you need a file to be closed in a deterministic manner, then you
must close it explicitly.

You don't typically need them to be closed in a completely fool-proof
deterministic fashion. If some other code catches your exceptions and
holds onto the traceback then it must know that can be delaying a few
file-closings, or the like.
The with statement is not implicit and never has been. Implicit
resource management is *insufficient* for the general resource
management case. It works fine for memory, it's okay for files
(until it isn't), it's terrible for thread locks and network
connections and database transactions. Those things require
*explicit* resource management.

Yes, I agree there are certain situations in which you certainly want
"with", or something like it. I've never disagreed with that
assertion at all. I just don't agree that for most Python code this
is the *typical* case.
To the extent that your code ever worked when you relied on this
detail, it will continue to work.

I've written plenty of Python code that relied on destructors to
deallocate resources, and the code always worked.
There are no plans to replace pythons refcounting with fancier GC
schemes that I am aware of.

This is counter to what other people have been saying. They have been
worrying me by saying that the refcounter may go away and so you may
not be able to rely on predictable object lifetimes in the future.
Nothing about Pythons memory management has changed. I know I'm
repeating myself here, but you just don't seem to grasp this
concept. Python has *never* had deterministic destruction of
objects. It was never guaranteed, and code that seemed like it
benefited from it was fragile.

It was not fragile in my experience. If a resource *positively*,
*absolutely* needed to be deallocated at a certain point in the code
(and occasionally that was the case), then I would code that way. But
that has been far from the typical case for me.
I'm talking about Python refcounts. For example, a subtle resource
leak that has caught me before is that tracebacks hold references to
locals in the unwound stack.

Yes, I'm aware of that. Most programs don't hold onto tracebacks for
long. If you are working with software that does, then, I agree, that
sometimes one will have to code things more precisely.
If you relied on refcounting to clean up a resource, and you needed
exception handling, the resource wasn't released until *after* the
exception unwound, which could be a problem. Also holding onto
tracebacks for latter processing (not uncommon in event based
programs) would artificially extend the lifetime of the resource. If
the resource you were managing was a thread lock this could be a
real problem.

Right -- I've always explicitly managed thread locks.
I really have no desire to code in C, thank you. I'd rather be coding
in Python. (Hence my [idle] desire for macros in Python, so that I
could do even more of my work in Python.)
In this particular conversation, I really don't think that theres much
to say beyond put up or shut up.

I think your attitude here is unPythonic.
The experts in the field have said that it's not practical.

Guido has occasionally said that he might consider a macro facility
for a future version of Python. Do these so-called experts know
something that he doesn't?
If you think they're wrong, you're going to need to prove it with
code, not by waving your hand.

I have existence proofs for them working well in a number of other
languages.
That doesn't make Lisp any better at AI programming than it is for
writing databases or spreadsheets or anything else.

Well, Lisp is also good for those things too. Lisp is good for just
about everything.

Except that it wasn't for scripting when I first learned Python, as
the start-up times on the Lisp-based competition was painfully slow.
Guile seems to start up quickly enough these days, but it doesn't seem
to be very widely used.
The language of the future will not be Common Lisp,

Yes, that's for sure.
and it won't be a well known dialect of Lisp.

It won't be *any* dialect that exists today, though, it is likely to
be derived from an existing one, and may share its name.
It will have many Lisp like features,

Yes, definitely.
and "true" Lispers will still claim it doesn't count, just as they
do about Ruby and Python today.

I'm a true Lisper (I haven't programmed much in Lisp in some time, but
I still think in Lisp, it being the one true language of programming
thought after all), and I claim that Python and Ruby are tantamount to
dialects of Lisp. Dialects that are sadly missing macros.

|>oug
 
M

Michele Simionato

I've written plenty of Python code that relied on destructors to
deallocate resources, and the code always worked.

You have been lucky:

$ cat deallocating.py
import logging

class C(object):
def __init__(self):
logging.warn('Allocating resource ...')

def __del__(self):
logging.warn('De-allocating resource ...')
print 'THIS IS NEVER REACHED!'

if __name__ == '__main__':
c = C()

$ python deallocating.py
WARNING:root:Allocating resource ...
Exception exceptions.AttributeError: "'NoneType' object has no
attribute 'warn'" in <bound method C.__del__ of <__main__.C object at
0xb7b9436c>> ignored

Just because your experience has been positive, you should not
dismiss the opinion who have clearly more experience than you on
the subtilities of Python.

Michele
 
D

Dennis Lee Bieber

I'm a true Lisper (I haven't programmed much in Lisp in some time, but
I still think in Lisp, it being the one true language of programming
thought after all), and I claim that Python and Ruby are tantamount to
dialects of Lisp. Dialects that are sadly missing macros.
On that line, I guess I'm a child of the language of number
crunching: FORTRAN...

To me, Python shows no relationship to LISP* <G> (I won't speak of
Ruby and its PERLish cursing)

LISP and FORTH are cousins... Python is closer to the REXX world
(though much more powerful as a general purpose language... REXX,
especially in the Amiga incarnation, was a very powerful glue/shell
language as any program that supplied an "AREXX port" could be directly
addressed and controlled -- or by supplying an AREXX library, become an
extension of the language. Python's subprocess module is a weak
imitation)



* {I did have SuperSoft LISP on my first computer, so I'm not totally
oblivious}
--
Wulfraed Dennis Lee Bieber KD6MOG
(e-mail address removed) (e-mail address removed)
HTTP://wlfraed.home.netcom.com/
(Bestiaria Support Staff: (e-mail address removed))
HTTP://www.bestiaria.com/
 
B

Ben Finney

Adam Pletcher said:
Does anyone have Python code for writing Targa (TGA) image files?

Please post your question as a new message, instead of a reply to an
existing thread that has nothing to do with the question you're
asking. Otherwise your message will be obscured among the many other
messages in the same thread.
 
H

Hrvoje Niksic

Douglas Alan said:
I think you overstate your case. Lispers understand iteration
interfaces perfectly well, but tend to prefer mapping fuctions to
iteration because mapping functions are both easier to code (they
are basically equivalent to coding generators) and efficient (like
non-generator-implemented iterators). The downside is that they are
not quite as flexible as iterators (which can be hard to code) and
generators, which are slow.

Why do you think generators are any slower than hand-coded iterators?
Consider a trivial sequence iterator:

$ python -m timeit -s 'l=[1] * 100
class foo(object):
def __init__(self, l):
self.l = l
self.i = 0
def __iter__(self):
return self
def next(self):
self.i += 1
try:
return self.l[self.i - 1]
except IndexError:
raise StopIteration
' 'tuple(foo(l))'
10000 loops, best of 3: 173 usec per loop

The equivalent generator is not only easier to write, but also
considerably faster:

$ python -m timeit -s 'l=[1] * 100
def foo(l):
i = 0
while 1:
try:
yield l
except IndexError:
break
i += 1
' 'tuple(foo(l))'
10000 loops, best of 3: 46 usec per loop
 
C

Chris Mellon

Sure there is -- smart pointers handle many sorts of situations, while
"with" only handles the case where the lifetime of the object
corresponds to the scope.

The entire point of RAII is that you use objects who's lifetime
corresponds with a scope. Smart pointers are an RAII technique to
manage refcounts, not a resource management technique in and of
themselves.

I've written plenty of Python code that relied on destructors to
deallocate resources, and the code always worked.

This is roughly equivilent to someone saying that they don't bother
initializing pointers to 0 in C, because it's always worked for them.
The fact that it works in certain cases (in the C case, when you're
working in the debug mode of certain compilers or standard libs) does
not mean that code that relies on it working is correct.
This is counter to what other people have been saying. They have been
worrying me by saying that the refcounter may go away and so you may
not be able to rely on predictable object lifetimes in the future.

Well, the official language implementation explicitly warns against
relying on the behavior you've been relying on. And of course, for the
purposes you've been using it it'll continue to work even if python
did eliminate refcounting - "soon enough" deallocation of non-time
sensitive resources. So I don't know what you're hollering about.

You're arguing in 2 directions here. You don't want refcounting to go
away, because you rely on it to close things exactly when there are no
more references. On the other hand, you're claiming that implicit
management and its pitfalls are fine because most of the time you
don't need the resource to be closed in a deterministic manner.

If you're relying on refcounting for timely, guaranteed,
deterministic resource managment then your code is *wrong* already,
for the same reason that someone who assumes that uninitialized
pointers in C will be 0 is wrong.

If you're relying on refcounting for "soon enough" resource management
then it'll continue to work no matter what GC scheme python may or may
not move to.
It was not fragile in my experience. If a resource *positively*,
*absolutely* needed to be deallocated at a certain point in the code
(and occasionally that was the case), then I would code that way. But
that has been far from the typical case for me.

Your experience was wrong, then. It's fragile because it's easy for
external callers to grab refcounts to your objects, and it's easy for
code modifications to cause resources to live longer. If you don't
*care* about that, then by all means, don't control the resource
explicitly. You can continue to do this no matter what - people work
with files like this in Java all the time, for the same reason they do
it in Python. Memory and files are not the end all of resources.

You're arguing against explicit resource management with the argument
that you don't need to manage resources. Can you not see how
ridiculously circular this is?
 
D

Douglas Alan

Why do you think generators are any slower than hand-coded iterators?

Generators aren't slower than hand-coded iterators in *Python*, but
that's because Python is a slow language. In a fast language, such as
a Lisp, generators are like 100 times slower than mapping functions.
(At least they were on Lisp Machines, where generators were
implemented using a more generator coroutining mechanism [i.e., stack
groups]. *Perhaps* there would be some opportunities for more
optimization if they had used a less general mechanism.)

CLU, which I believe is the language that invented generators, limited
them to the power of mapping functions (i.e., you couldn't have
multiple generators instantiated in parallel), making them really
syntactic sugar for mapping functions. The reason for this limitation
was performance. CLU was a fast language.

|>oug
 
D

Douglas Alan

You have been lucky:

No I haven't been lucky -- I just know what I'm doing.
$ cat deallocating.py
import logging

class C(object):
def __init__(self):
logging.warn('Allocating resource ...')

def __del__(self):
logging.warn('De-allocating resource ...')
print 'THIS IS NEVER REACHED!'

if __name__ == '__main__':
c = C()

$ python deallocating.py
WARNING:root:Allocating resource ...
Exception exceptions.AttributeError: "'NoneType' object has no
attribute 'warn'" in <bound method C.__del__ of <__main__.C object at
0xb7b9436c>> ignored

Right. So? I understand this issue completely and I code
accordingly.
Just because your experience has been positive, you should not
dismiss the opinion who have clearly more experience than you on
the subtilities of Python.

I don't dismiss their opinion at all. All I've stated is that for my
purposes I find that the refcounting semantics of Python to be useful,
expressive, and dependable, and that I wouldn't like it one bit if
they were removed from Python.

Those who claim that the refcounting semantics are not useful are the
ones who are dismissing my experience. (And the experience of
zillions of other Python programmers who have happily been relying on
them.)

|>oug
 
D

Douglas Alan

Dennis Lee Bieber said:
LISP and FORTH are cousins...

Not really. Their only real similarity (other than the similarities
shared by most programming languages) is that they both use a form of
Polish notation.

|>oug
 
D

Douglas Alan

Chris Mellon said:
You're arguing against explicit resource management with the argument
that you don't need to manage resources. Can you not see how
ridiculously circular this is?

No. It is insane to leave files unclosed in Java (unless you know for
sure that your program is not going to be opening many files) because
you don't even know that the garbage collector will ever even run, and
you could easily run out of file descriptors, and hog system
resources.

On the other hand, in Python, you can be 100% sure that your files
will be closed in a timely manner without explicitly closing them, as
long as you are safe in making certain assumptions about how your code
will be used. Such assumptions are called "preconditions", which are
an understood notion in software engineering and by me when I write
software.

|>oug
 
C

Chris Mellon

No. It is insane to leave files unclosed in Java (unless you know for
sure that your program is not going to be opening many files) because
you don't even know that the garbage collector will ever even run, and
you could easily run out of file descriptors, and hog system
resources.

On the other hand, in Python, you can be 100% sure that your files
will be closed in a timely manner without explicitly closing them, as
long as you are safe in making certain assumptions about how your code
will be used. Such assumptions are called "preconditions", which are
an understood notion in software engineering and by me when I write
software.

Next time theres one of those "software development isn't really
engineering" debates going on I'm sure that we'll be able to settle
the argument by pointing out that relying on *explicitly* unreliable
implementation details is defined as "engineering" by some people.
 
H

Hrvoje Niksic

Douglas Alan said:
Generators aren't slower than hand-coded iterators in *Python*, but
that's because Python is a slow language.

But then it should be slow for both generators and iterators.
*Perhaps* there would be some opportunities for more optimization if
they had used a less general mechanism.)

Or if the generators were built into the language and directly
supported by the compiler. In some cases implementing a feature is
*not* a simple case of writing a macro, even in Lisp. Generators may
well be one such case.
 
D

Douglas Alan

Next time theres one of those "software development isn't really
engineering" debates going on I'm sure that we'll be able to settle
the argument by pointing out that relying on *explicitly* unreliable
implementation details is defined as "engineering" by some people.

The proof of the pudding is in it's eating. I've worked on very large
programs that exhibited very few bugs, and ran flawlessly for many
years. One managed the memory remotely of a space telescope, and the
code was pretty tricky. I was sure when writing the code that there
would be a number of obscure bugs that I would end up having to pull
my hair out debugging, but it's been running flawlessly for more than
a decade now, without require nearly any debugging at all.

Engineering to a large degree is knowing where to dedicate your
efforts. If you dedicate them to where they are not needed, then you
have less time to dedicate them to where they truly are.

|>oug
 
S

Steve Holden

Douglas said:
No I haven't been lucky -- I just know what I'm doing.


Right. So? I understand this issue completely and I code
accordingly.


I don't dismiss their opinion at all. All I've stated is that for my
purposes I find that the refcounting semantics of Python to be useful,
expressive, and dependable, and that I wouldn't like it one bit if
they were removed from Python.

Those who claim that the refcounting semantics are not useful are the
ones who are dismissing my experience. (And the experience of
zillions of other Python programmers who have happily been relying on
them.)

|>oug

"Python" doesn't *have* any refcounting semantics. If you rely on the
behavior of CPython's memory allocation and garbage collection you run
the risk of producing programs that won't port tp Jython, or IronPython,
or PyPy, or ...

This is a trade-off that many users *are* willing to make.

regards
Steve
--
Steve Holden +1 571 484 6266 +1 800 494 3119
Holden Web LLC/Ltd http://www.holdenweb.com
Skype: holdenweb http://del.icio.us/steve.holden
--------------- Asciimercial ------------------
Get on the web: Blog, lens and tag the Internet
Many services currently offer free registration
----------- Thank You for Reading -------------
 

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top