Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

constant in python?

659 views
Skip to first unread message

liam

unread,
Aug 17, 2001, 3:36:33 PM8/17/01
to
is there a data type like the const in c/c++? ive been combing through the
doc and it doesnt seem to have one or am i missing something somewhere?


Alex Martelli

unread,
Aug 17, 2001, 4:01:20 PM8/17/01
to
"liam" <lcam...@ubytes.com> wrote in message
news:Bmef7.269051$qv3.55...@nnrp5-w.sbc.net...

> is there a data type like the const in c/c++? ive been combing through the
> doc and it doesnt seem to have one or am i missing something somewhere?

A reasonably popular solution is my "Constants in Python" recipe at:

http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207


Alex

liam

unread,
Aug 17, 2001, 4:48:53 PM8/17/01
to
i found a similar example on the net i was just making sure. seems kinda
alot of work just to get a constant. even perl has "use constant" and thats
about the ugliest language around :)
"Alex Martelli" <ale...@yahoo.com> wrote in message
news:9ljt9...@enews2.newsguy.com...

Brian Quinlan

unread,
Aug 17, 2001, 5:44:01 PM8/17/01
to liam, pytho...@python.org
> i found a similar example on the net i was just making sure.
> seems kinda alot of work just to get a constant. even perl
> has "use constant" and thats about the ugliest language around :)

The questions is why do you need explicit language support for
constants? Just don't change the value and it should behave constant
enough for you.


Alex Martelli

unread,
Aug 18, 2001, 3:54:35 AM8/18/01
to
"liam" <lcam...@ubytes.com> wrote in message
news:sqff7.779$2k4....@news.pacbell.net...

> i found a similar example on the net i was just making sure. seems kinda
> alot of work just to get a constant. even perl has "use constant" and
thats
> about the ugliest language around :)
...
> > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207

Note that the purpose of the work is ensuring an exception gets
raised if one accidentally tries to rebind a module-attribute that
is meant to be 'constant' (read-only). "to get a constant", i.e.,
an attribute that does not change, you have to do nothing special:
just don't rebind it, and it will not change.

I agree that in most cases it's not worth it -- it's not important
enough to ensure exceptions get raised for such programming
errors, as an exception will be raised soon afterwards if you run
decent tests AND it's actually important for the attribute not to
be re-bound (often you'll find there's no real need for the
'constantness' and the program works fine even if things do
change:-). The real purpose of recipe 65207 is showing how
to use an instance in lieu of a module and thereby gain the
ability to use __getattr__/__setattr__ on it.

But if it's not important enough to raise exceptions on such
errors, for it to be worth including a few lines of code in your
site-configuration script, how can it POSSIBLY be important
enough to be worth making the language itself bigger and
more complicated?! ANY feature in a language must pull its
own weight, else you end up with huge, redundant languages.

If something can be done with a few lines of code in the
language as it is, it requires very strong motivation for that
something to become a built-in language mechanism: most
particularly, that something must be a very important task,
frequently performed, and with a substantial advantage (in
terms of ease of use, performance, or simply the pervasive
effects of standardization) to have it in the language itself.

I think few languages have followed these guidelines for
design and evolution as closely as Python -- not that Python
has been perfect about it, of course, but quite reasonably
close to that ideal. I think that "constants" are a good
example of something that should NOT be in the language
itself, exactly because it's a minor issue and it can be
easily implemented without too much trouble (it could
be placed in the standard library, which has somewhat
laxer requirements than the language proper, but that's
pretty iffy too). Good examples of things that _are_
eventually added to the language include the list
comprehensions added in 2.0, nested scopes added in
2.1, iterators added in 2.2. THESE are language features
that pull their own weight (and even on this you will
find disagreement -- a number of practising pythmen are
rather minimalists than pragmatists:-).


Alex

Michael Ströder

unread,
Aug 18, 2001, 7:36:53 AM8/18/01
to
Alex Martelli wrote:
>
> > > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207

>
> If something can be done with a few lines of code in the
> language as it is, it requires very strong motivation for that
> something to become a built-in language mechanism:

I would guess that the recipe above causes some performance penalty.

> I think that "constants" are a good
> example of something that should NOT be in the language
> itself, exactly because it's a minor issue and it can be
> easily implemented without too much trouble

Disclaimer: I'm not a compiler expert.
IMHO constants are useful in compiled languages because they are
immutable and therefore a compiler can insert them as "in-line"
operands for optimization.

Ciao, Michael.

Michael Ströder

unread,
Aug 18, 2001, 7:37:52 AM8/18/01
to

To avoid that another developer in the team changes the constant
accidently?

Ciao, Michael.

liam

unread,
Aug 18, 2001, 10:35:12 AM8/18/01
to
agreed, its fine to leave it to yourself to know not to change a constant
but if its a big project constants would be a nice plus so your associates
dont mess thing up, accidently?
"Michael Ströder" <mic...@stroeder.com> wrote in message
news:3B7E5390...@stroeder.com...

Alex Martelli

unread,
Aug 18, 2001, 12:42:37 PM8/18/01
to
"liam" <lcam...@ubytes.com> wrote in message
news:62vf7.4717$Vs2.4...@news.pacbell.net...

> agreed, its fine to leave it to yourself to know not to change a constant
> but if its a big project constants would be a nice plus so your associates
> dont mess thing up, accidently?

In a big project, the overhead of writing and installing the "constants
module" I explain in my Cookbook recipe is surely less than 1/10000
of the project effort -- so, 0.01% is NOT a big price to pay if you DO
consider it "a nice plus" to get some protection against accidents of
this nature.


Alex

Alex Martelli

unread,
Aug 18, 2001, 12:59:30 PM8/18/01
to
"Michael Ströder" <mic...@stroeder.com> wrote in message
news:3B7E5355...@stroeder.com...

> Alex Martelli wrote:
> >
> > > > http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65207
> >
> > If something can be done with a few lines of code in the
> > language as it is, it requires very strong motivation for that
> > something to become a built-in language mechanism:
>
> I would guess that the recipe above causes some performance penalty.

Why guess, when you can measure?

Say const.py is like in the recipe, normal.py is an empty
normal module, and test.py contains:

import time, const, normal

start = time.clock()
const.magic = 23
sum = 0L
for i in range(100000):
sum += const.magic
stend = time.clock()

print "const : %5.2f"%(stend-start)

start = time.clock()
normal.magic = 23
sum = 0L
for i in range(100000):
sum += normal.magic
stend = time.clock()

print "normal: %5.2f"%(stend-start)

Here are three runs on my box:

D:\ian\good>python test.py
const : 1.44
normal: 1.60

D:\ian\good>python test.py
const : 1.63
normal: 1.53

D:\ian\good>python test.py
const : 1.41
normal: 1.53

See? No statistically significant difference penalizes the
const module vs a normal module -- it so happens the
loop using the const module was faster two times out
of three, but this is indeed happenstance.

Moral: never guess at performance -- it often baffles the
intuition even of the most accomplished expert. MEASURE.


> > I think that "constants" are a good
> > example of something that should NOT be in the language
> > itself, exactly because it's a minor issue and it can be
> > easily implemented without too much trouble
>
> Disclaimer: I'm not a compiler expert.
> IMHO constants are useful in compiled languages because they are
> immutable and therefore a compiler can insert them as "in-line"
> operands for optimization.

Sure, no doubt you can gain a microsecond or two each
time a constant is a literal rather than having to be fetched
anew from the module owning it. But, so what?! Any
good Python developer using a module attribute (that is
not meant to change) in a tight loop that'a performance
hot-spot would surely 'hoist' the module access out of
the loop, using a local function variable instead (which
is just as fast to access as a literal).

Don't guess -- MEASURE: change the above program to
consider literals and hoisting too: and see what comes up...

The design of the Python language is *NOT* traditionally
driven by an obsession with micro-optimizations -- thanks
be, or it would most definitely _NOT_ be Python. These
misplaced performance-related worries surely can't justify
perverting the language by adding a built-in "constant".


Alex

Paul Rubin

unread,
Aug 18, 2001, 1:50:18 PM8/18/01
to
"Brian Quinlan" <Bri...@ActiveState.com> writes:
> The questions is why do you need explicit language support for
> constants? Just don't change the value and it should behave constant
> enough for you.

I dislike the runtime system and the doctrinaire OO culture that's
grown up around Java, but having constants, and rigorously enforcing
protection of private class members and methods is one thing Java did
right. It makes the "applet sandbox" very straightforward. This
is useful for web browser extensions but also for security coprocessors
(Dallas Java iButton, Nci

I understand Python has some kind of "restricted execution" package
that might take care of this but I haven't studied it yet. Perl has
one but it's kludgy.

Paul Rubin

unread,
Aug 18, 2001, 1:59:17 PM8/18/01
to
"Brian Quinlan" <Bri...@ActiveState.com> writes:
> The questions is why do you need explicit language support for
> constants? Just don't change the value and it should behave constant
> enough for you.

I don't like the Java runtime system or the doctrinaire OO culture
that's grown up around Java, but enforcing constantness and the
privacy of non-public class instance variables and methods is one
thing the Java language did right. It makes the "applet sandbox" a
natural idea. This is useful not just for browser extensions, but for
programmable security coprocessors (Dallas iButton, NCipher SEE),
stored procedures in multi-user databases (Oracle 8i) and other
environments where you may want to hand a class instance to
potentially malicious code.

Perl has a "restricted execution" scheme that's pretty messy. I
understand Python also has such a scheme, but I haven't studied it yet.

Bengt Richter

unread,
Aug 18, 2001, 3:22:32 PM8/18/01
to

I agree, but the happenstances can be separated out to a fair degree,
even if you're on line and background stuff may be happening:

(Not very elegant cutting and pasting, but here's what I like to do :)
_______________________________________________

import time, const, normal

const.magic = 23
normal.magic = 23
sumc = 0L
sumn = 0L
cdir={}
ndir={}
for i in range(100000):
start = time.clock()
sumc += const.magic
stend = time.clock()
sumn += normal.magic
stend2 = time.clock()
dt = int((stend-start)*1.0e9) #nanoseconds
if cdir.has_key(dt):
cdir[dt] += 1
else:
cdir[dt] = 1

dt = int((stend2-stend)*1.0e9) #nanoseconds
if ndir.has_key(dt):
ndir[dt] += 1
else:
ndir[dt] = 1

print '-- const case --'
vk = [(v,k) for k,v in cdir.items()]
vk.sort()
vk.reverse()
for v,k in vk[:10]:
print "%7d %10d" % ( v, k )

print '-- normal case --'
vk = [(v,k) for k,v in ndir.items()]
vk.sort()
vk.reverse()
for v,k in vk[:10]:
print "%7d %10d" % ( v, k )

__________________
Result: (NT4sp3,300mhzP2,320MB ram, Python 2.1)

-- const case --
54910 31847
21574 31009
20695 32685
1883 33523
327 30171
119 34361
72 35199
54 38552
49 39390
28 36038
-- normal case --
55261 30171
26861 31009
14372 29333
2785 31847
305 32685
51 37714
41 28495
31 38552
27 36876
19 39390

But note that you don't have to run 100k trials
to get useful results, since you see the outliers
that might otherwise get averaged in. Here's for 1k:

-- const case --
549 31009
293 30171
135 31847
11 32685
6 29333
1 1063542
1 364571
1 46095
1 35199
1 34361
-- normal case --
646 29333
205 28495
128 30171
13 31009
1 402285
1 99733
1 93028
1 68723
1 63695
1 54476

Frederic Giacometti

unread,
Aug 18, 2001, 3:49:26 PM8/18/01
to

"Michael Ströder" <mic...@stroeder.com> wrote in message
news:3B7E5390...@stroeder.com...

What about every other declarations in the module scope (def, class ....)?

Actually, such 'accidents' can't happen, thanks to name scoping and to the
import mechanism.
You can't mess up another module, unless you want to - no confusion is
possible -.

FG

Skip Montanaro

unread,
Aug 18, 2001, 2:15:24 PM8/18/01
to Alex Martelli, mic...@stroeder.com, pytho...@python.org

>> IMHO constants are useful in compiled languages because they are
>> immutable and therefore a compiler can insert them as "in-line"
>> operands for optimization.

Alex> Sure, no doubt you can gain a microsecond or two each time a
Alex> constant is a literal rather than having to be fetched anew from
Alex> the module owning it. But, so what?! Any good Python developer
Alex> using a module attribute (that is not meant to change) in a tight
Alex> loop that'a performance hot-spot would surely 'hoist' the module
Alex> access out of the loop, using a local function variable instead
Alex> (which is just as fast to access as a literal).

I'll add a couple things to reinforce Alex's arguments. One, see PEP 0266
for a possible solution to this particular performance problem, small though
it is. Two, constant literals used within a function, e.g., the "5" in this
function:

def f(a):
return a+5

are accessed no faster than local variables the way the current virtual
machine works. Constant literals do not appear in the instruction stream
itself. They are stored in a per-function array of constants which is
accessed with roughly the same speed as the local variables array. In fact,
some things you'd naively think would be faster (because they would be in
most any similar C program), such as

def f(a):
return a+(1.0+8j)

are actually slower, because the compiler currently generates two constant
loads and an add. (Same thing applies for tuples of constants.)

Alex> The design of the Python language is *NOT* traditionally driven by
Alex> an obsession with micro-optimizations -- thanks be, or it would
Alex> most definitely _NOT_ be Python. These misplaced performance-
Alex> related worries surely can't justify perverting the language by
Alex> adding a built-in "constant".

Agreed. There are far more important things to worry about performance-
wise. Consider, for example, the table of dynamic opcode frequencies
Marc-Andre Lemburg posted to python-dev in July 2000:

http://mail.python.org/pipermail/python-dev/2000-July/007609.html

Ignore the SET_LINENO counts because "python -O" already zaps them. Of the
remaining opcodes in his table, roughly 65% of them do nothing but move data
onto, off of, or within the stack. I consider all the following as data
movement opcodes: LOAD_FAST, LOAD_CONST, LOAD_NAME, LOAD_GLOBAL, STORE_FAST,
POP_TOP, LOAD_ATTR, STORE_NAME, and STORE_ATTR.

If you want some performance boost, think about ways you might delete about
90% of those instructions. ;-)

--
Skip Montanaro (sk...@pobox.com)
http://www.mojam.com/
http://www.musi-cal.com/

Brian Quinlan

unread,
Aug 18, 2001, 2:27:52 PM8/18/01
to Paul Rubin, pytho...@python.org
Paul Rubin:

> I dislike the runtime system and the doctrinaire OO culture that's
> grown up around Java, but having constants, and rigorously enforcing
> protection of private class members and methods is one thing Java did
> right.

If you believe that then Python might not be the language for you. The
problem with enforcing privacy is that the designer can seldom
anticipate all of the possible uses of their code and placing arbitrary
access restriction can make it impossible for the user to accomplish
their task.

> It makes the "applet sandbox" very straightforward. This
> is useful for web browser extensions but also for security
coprocessors

> (Dallas Java iButton, Nci)

Python is a general purpose programming language and its design should
not be significantly compromised to make a particular (uncommon) usage
more convenient i.e. security environments.

Cheers,
Brian


Alex Martelli

unread,
Aug 18, 2001, 7:36:34 PM8/18/01
to
"Brian Quinlan" <br...@sweetapp.com> wrote in message
news:mailman.998159307...@python.org...

> Paul Rubin:
> > I dislike the runtime system and the doctrinaire OO culture that's
> > grown up around Java, but having constants, and rigorously enforcing
> > protection of private class members and methods is one thing Java did
> > right.
>
> If you believe that then Python might not be the language for you. The

OTOH, he can get the worst of both words (from his POV) -- Java's
runtime (JVM) and libraries (doctrinaire OO) *AND* Python's lack
of enforced protection -- in Jython:-).

> problem with enforcing privacy is that the designer can seldom
> anticipate all of the possible uses of their code and placing arbitrary
> access restriction can make it impossible for the user to accomplish
> their task.

Hear, hear! Designers aren't omniscient and a language that lets
me workaround a limitation in the design of a framework or library
I need to use is just what I need.


> > It makes the "applet sandbox" very straightforward. This
> > is useful for web browser extensions but also for security
> coprocessors
> > (Dallas Java iButton, Nci)
>
> Python is a general purpose programming language and its design should
> not be significantly compromised to make a particular (uncommon) usage
> more convenient i.e. security environments.

Yep. Besides, rexec and Bastion (could use some spiffying up,
but) are pretty good for this.


Alex

Alex Martelli

unread,
Aug 18, 2001, 7:44:28 PM8/18/01
to
"Skip Montanaro" <sk...@pobox.com> wrote in message
news:mailman.998158617...@python.org...
...

> remaining opcodes in his table, roughly 65% of them do nothing but move
data
> onto, off of, or within the stack. I consider all the following as data
> movement opcodes: LOAD_FAST, LOAD_CONST, LOAD_NAME, LOAD_GLOBAL,
STORE_FAST,
> POP_TOP, LOAD_ATTR, STORE_NAME, and STORE_ATTR.
>
> If you want some performance boost, think about ways you might delete
about
> 90% of those instructions. ;-)

Hmmm, I'll byte -- by having joined LOAD_this_STORE_that bytecodes (5 kinds
of loads, 3 kinds of stores, that's 15 new bytecodes) and a few
call-and-poptop
ones? And a peephole optimizer to change the bytecode stream coming from
the current compiler to one using the new bytecodes (and making a few more
minor opts while he's at it)...?

Or am I missing something obvious...? 'cause I don't think that would
delete
90% of the datamovement instructions -- maybe 30 to 40% or so...?


Alex

Alex Martelli

unread,
Aug 18, 2001, 7:45:53 PM8/18/01
to
"Paul Rubin" <phr-...@nightsong.com> wrote in message
news:7xd75tz...@ruckus.brouhaha.com...
...

> Perl has a "restricted execution" scheme that's pretty messy. I
> understand Python also has such a scheme, but I haven't studied it yet.

It's un-messy, though rather rough-cut at this point. Best
coverage is AMK's at http://py-howto.sourceforge.net/rexec/rexec.html.


Alex

Peter Hansen

unread,
Aug 19, 2001, 3:43:27 AM8/19/01
to
[quoting style "corrected" by reordering]

liam wrote:
> "Michael Ströder" <mic...@stroeder.com> wrote:


> > Brian Quinlan wrote:
> > > The questions is why do you need explicit language support for
> > > constants? Just don't change the value and it should behave constant
> > > enough for you.
> >
> > To avoid that another developer in the team changes the constant
> > accidently?
>

> agreed, its fine to leave it to yourself to know not to change a constant
> but if its a big project constants would be a nice plus so your associates
> dont mess thing up, accidently?

Two words: "coding standard"

PORT_NAME = 'COM1'
portName = 'COM1'

Only one of these may be changed by my "associates" ... no need for
a "const" keyword (nor even Alex's little gem in most cases) ...

(And, as usual with Python, it still leaves the door open for those
cases where someone _really_ wants to change a so-called constant,
probably during an awkward debugging session, or for a special test
case or something. _Enforcing_ constancy would prevent that, which
would not be very Pythonic.)

--
----------------------
Peter Hansen, P.Eng.
pe...@engcorp.com

Paul Rubin

unread,
Aug 19, 2001, 3:31:40 AM8/19/01
to
"Alex Martelli" <ale...@yahoo.com> writes:
> > problem with enforcing privacy is that the designer can seldom
> > anticipate all of the possible uses of their code and placing arbitrary
> > access restriction can make it impossible for the user to accomplish
> > their task.
>
> Hear, hear! Designers aren't omniscient and a language that lets
> me workaround a limitation in the design of a framework or library
> I need to use is just what I need.

The trouble is, the very existence of a workaround is sometimes itself
a limitation, e.g. in implementing an applet sandbox.

> > Python is a general purpose programming language and its design should
> > not be significantly compromised to make a particular (uncommon) usage
> > more convenient i.e. security environments.
>
> Yep. Besides, rexec and Bastion (could use some spiffying up,
> but) are pretty good for this.

I'll check into those. However, a true general purpose language
should be useable in all environments.

If Python had Scheme-like lexical closures, that might be enough
to solve this particular problem.

Paul Rubin

unread,
Aug 19, 2001, 3:52:34 AM8/19/01
to
"Alex Martelli" <ale...@yahoo.com> writes:
> It's un-messy, though rather rough-cut at this point. Best
> coverage is AMK's at http://py-howto.sourceforge.net/rexec/rexec.html.

Thanks, rexec/bastion looks nice and seems to take care of the
problem. I didn't see that there were enough pre-existing Python
primitives to do that. I'll have to look at the rexec/bastion code
since it will probably be instructive.

An alternative may be to use one of the remote object schemes to put
the restricted object in a separate Unix process (maybe even on a
separate machine) from the caller. Then the restricted object could
implement its own access policy and generically defeating the control
would require to breaking Unix security. This is probably the most
secure possible scheme, but its limitations may not always be
tolerable.

Paul Rubin

unread,
Aug 19, 2001, 4:01:51 AM8/19/01
to
"Brian Quinlan" <br...@sweetapp.com> writes:
> If you believe that then Python might not be the language for you. The
> problem with enforcing privacy is that the designer can seldom
> anticipate all of the possible uses of their code and placing arbitrary
> access restriction can make it impossible for the user to accomplish
> their task.

Nonetheless, that's the desired outcome sometimes. Any networked
system has to include security features the whole POINT of which is to
make certain "tasks" impossible. Anyway, the RExec/Bastion package
seems to accomplish what is needed, pretty much.

Alex Martelli

unread,
Aug 19, 2001, 5:27:49 AM8/19/01
to
"Paul Rubin" <phr-...@nightsong.com> wrote in message
news:7xk800i...@ruckus.brouhaha.com...

> "Alex Martelli" <ale...@yahoo.com> writes:
> > It's un-messy, though rather rough-cut at this point. Best
> > coverage is AMK's at http://py-howto.sourceforge.net/rexec/rexec.html.
>
> Thanks, rexec/bastion looks nice and seems to take care of the
> problem. I didn't see that there were enough pre-existing Python
> primitives to do that. I'll have to look at the rexec/bastion code
> since it will probably be instructive.

It simply relies on the fact that code executed in a (global)
dictionary namespace whose __builtins__ entry does not
refer to the real __builtin__ module is intepreted as being
"restricted". Restricted code is denied access to some of
Python's normal introspection facilities -- the interpreter
sees to that. So, for example, a BastionClass instance has
a _get_ method that's a function, supplied to it by the
factory function Bastion, which in turn holds the real
object as a default argument. Normal Python code could
introspect that and get at the real object; restricted code
cannot, because its introspection abilities are limited.


> An alternative may be to use one of the remote object schemes to put
> the restricted object in a separate Unix process (maybe even on a
> separate machine) from the caller. Then the restricted object could
> implement its own access policy and generically defeating the control
> would require to breaking Unix security. This is probably the most
> secure possible scheme, but its limitations may not always be
> tolerable.

Yes, putting the code whose execution is being restricted
in another process (maybe in another machine) *IS* a huge
step up in security. Denial-of-service attacks via the untrusted
code become MUCH easier to defend against, for example: a
watchdog process can monitor the untrusted-process's resource
consumption and terminate it if need be -- the untrusted process
can be run with enforced priorities, under a userid with a very
limited disk-quota, etc, etc. (It's all quite feasible under NT,
too, by the way -- just a little bit costly, because starting a new
process is heavier, but once that's done the monitoring
facilities are quite decent.). I do agree that sometimes the
overall jump up in complexity and performance overhead
is just something you can't afford.

Something I've never done is keeping just two processes
up, the monitoring/untrusted and the monitored one -- the
process-startup overhead would only be paid on the rare
occasions when the untrusted process is terminated. Sort
of like an untrusted-machine approach to firewalling -- you
don't build a new machine for each network transaction in
that case:-). But I've never thought deeply enough about
potential vulnerabilities -- could one clever piece of
untrusted code hide eggs in the untrusted process and
exploit a further unrelated piece of untrusted code loaded
later with different privileges, for example?


Alex

Brian Quinlan

unread,
Aug 19, 2001, 5:07:19 AM8/19/01
to pytho...@python.org
Paul wrote:
> > Hear, hear! Designers aren't omniscient and a language that lets
> > me workaround a limitation in the design of a framework or library
> > I need to use is just what I need.
>
> The trouble is, the very existence of a workaround is sometimes itself
> a limitation, e.g. in implementing an applet sandbox.

I'm sure that your particular application is close to your heart but
it's fortunately not a problem most of us have to deal with.

> I'll check into those. However, a true general purpose language
> should be useable in all environments.

Name one language that is useable in ALL environments.


Alex Martelli

unread,
Aug 19, 2001, 6:31:22 AM8/19/01
to
"Paul Rubin" <phr-...@nightsong.com> wrote in message
news:7xsneoi...@ruckus.brouhaha.com...
...

> > Hear, hear! Designers aren't omniscient and a language that lets
> > me workaround a limitation in the design of a framework or library
> > I need to use is just what I need.
>
> The trouble is, the very existence of a workaround is sometimes itself
> a limitation, e.g. in implementing an applet sandbox.

It would be, yes, IF untrusted code subject to restricted-mode execution
had full access to such workarounds. Fortunately, this is not the case
with Python: the runtime knows when it's executing code 'restrictedly'
(thus, presumably, untrusted code), by the simple test of checking if
the current global namespace dictionary's __builtin__ refers to
something else than the true __builtins__. Restricted code doesn't
have full introspection abilities, and this lets you sandbox it in.

E.g., try the following in an interactive session:

>>> realthing = __builtins__
>>> class X:
... def f(self): print self
...
>>> x=X()
>>> x.f()
<__main__.X instance at 007994DC>
>>> x.__dict__
{}
>>> X.__dict__
{'f': <function f at 0079A18C>, '__doc__': None, '__module__': '__main__'}
>>> __builtins__=__builtins__.__dict__.copy()
>>> x.f()
<__main__.X instance at 007994DC>
>>> X.__dict__
Traceback (most recent call last):
File "<stdin>", line 1, in ?
RuntimeError: class.__dict__ not accessible in restricted mode
>>> __builtins__ = realthing
>>> X.__dict__
{'f': <function f at 0079A18C>, '__doc__': None, '__module__': '__main__'}
>>>

Here, we saved a reference to the real-thing builtins, so we could
proclaim ourselves trusted again by re-assigning __builtins__ (of
course, you normally wouldn't supply that 'real-thing' to untrusted
code:-). But as long as our __builtins__ didn't refer to the
real thing, we were untrusted and thus running in restricted
mode. Since you clearly do have to be selective in what builtins
you let a piece of untrusted code access, identifying restricted
mode with non-kosher __builtins__ kills two birds with one stone.


> > > Python is a general purpose programming language and its design should
> > > not be significantly compromised to make a particular (uncommon) usage
> > > more convenient i.e. security environments.
> >
> > Yep. Besides, rexec and Bastion (could use some spiffying up,
> > but) are pretty good for this.
>
> I'll check into those. However, a true general purpose language
> should be useable in all environments.

I differ from this philosophy, which seems to shade into a "one
language to bind them all" design guideline. For example, I
consider machine-language to be "a true general purpose"
one, but that doesn't imply it has to be decenty deployable
in all environments -0- it's QUITE reasonable to require that
a binary-compatible machine or emulator thereof be part of
any environment in which the language is "useable".

In other terms, "all environments" is a serious overbid, I
believe. Is there a good Common Lisp compiler/runtime
for a 4-bit microcontroller with 4KB ROM and 256 bytes
of RAM? Probably not, but that doesn't mean Lisp isn't
"a true general purpose language", as long as it's deployable
in all *SUITABLE* environments -- ones 'powerful' enough
in terms of available hardware and software resources
(enough CPU power, ROM/storage, RAM, and underlying
software infrastructure).


> If Python had Scheme-like lexical closures, that might be enough
> to solve this particular problem.

It has lexical closures where a name at an intermediate
scope cannot be rebound from code in a nested scope,
somewhat like Java in this specific respect -- midway
between Scheme, that lets all names be freely rebound
(well, ALMOST all names), and Haskell, which doesn't
support the very concept of rebinding in any context
(I know there are better examples than Haskell for the
concept of single-assignment languages, it's just that
none comes to mind right now:-).


Alex

Skip Montanaro

unread,
Aug 19, 2001, 8:56:35 AM8/19/01
to Paul Rubin, pytho...@python.org
Alex> Yep. Besides, rexec and Bastion (could use some spiffying up,
Alex> but) are pretty good for this.

Paul> I'll check into those. However, a true general purpose language
Paul> should be useable in all environments.

All general purpose languages have some things they are better at than
others. C, Python, and Lisp are all general purpose languages, but each is
better at some things than others. If Java is better at web-based security
type stuff for your purposes, use it. C, Python and most dialects of Lisp
were around before such stuff was commonly done.

when-dueling-choose-your-weapon-wisely-ly y'rs,

Bernd Nawothnig

unread,
Aug 19, 2001, 12:33:42 PM8/19/01
to
On 19 Aug 2001 00:31:40 -0700, Paul Rubin <phr-...@nightsong.com> wrote:

> "Alex Martelli" <ale...@yahoo.com> writes:
>>> problem with enforcing privacy is that the designer can seldom
>>> anticipate all of the possible uses of their code and placing arbitrary
>>> access restriction can make it impossible for the user to accomplish
>>> their task.

Access restriction should never be used to arbitrarily prevent a user from
performing a task. The only idea behind restriction is to hide internal
details for having more stable code. If a class (by hiding details) is not
offering all the possibilities it clearly could offer, it is simply bad
designed (of course this happens). But to think removing all 'private' and
'protected' restrictions from such a bad designed class would really solve a
problem is foolish. You will only get deeper into the mess. One basic
priniple of OOP is providing a lot of methods - may be much more than you
actually need. Yes, good design isn't easy and nobody has ever said that OOP
alone is a guarantee for perfect code.

If you are missing feautures you can't easily implement, you should contact
the author - or use other code. Workarounds (or the possibility of doing so)
should never be a strong principle of software design. Almost every time one
is paying a high price for this behaviour - this may be years later.

The lack of access restriction possibilities should not be reinterpreted
into a feature. If it would be so ingenious _not_ to have them, a
substantial number of C++ programmers would put a 'public:' as first
statement in every class and never write a 'private:' or 'protected:'. I
never heard of this. It is a design decision to keep python simple and easy
to learn (and simplicity is a feature) - not more. One may say: "In my
opinion access restriction is not neccessary" - this is ok for many small
and medium projects.

>> Hear, hear! Designers aren't omniscient

They are not omniscient but they should have visions. And accepting these
visions and live and work with them (of course after choosing a suitable
design first) seems to me being far more better than using brute force and
quick hacks which only means: Only my point of view is right, nothing else
and my first choice would be programming against any idea which is not mine.

>> and a language that lets me workaround a limitation in the design of a
>> framework or library I need to use is just what I need.

> [...] the very existence of a workaround is sometimes itself a limitation,

Indeed. But this tends not to be seen by omniscient people :-)

Bernd

Paul Rubin

unread,
Aug 19, 2001, 3:21:07 PM8/19/01
to
"Brian Quinlan" <br...@sweetapp.com> writes:
> > The trouble is, the very existence of a workaround is sometimes itself
> > a limitation, e.g. in implementing an applet sandbox.
>
> I'm sure that your particular application is close to your heart but
> it's fortunately not a problem most of us have to deal with.

The implementers of Grail, a web browser written in Python that runs
Python applets, had to deal with it. Similarly the developers of
RExec/Bastion thought it was an important enough problem to develop a
special module for it. Perl has something similar.

> > I'll check into those. However, a true general purpose language
> > should be useable in all environments.
>
> Name one language that is useable in ALL environments.

Smalltalk and Lisp are Python-like languages that have been used as
the basis for complete computing environments (PARC Smalltalk system
and MIT Lisp Machine). I don't see why Python shouldn't be useable
on a similar scale.

Alex Martelli

unread,
Aug 19, 2001, 3:00:34 PM8/19/01
to
"Bernd Nawothnig" <Bernd.N...@t-online.de> wrote in message
news:slrn9nvq2n.3vvtj2...@Asterix.t-online.de...
...

> >> Hear, hear! Designers aren't omniscient
>
> They are not omniscient but they should have visions. And accepting these
> visions and live and work with them (of course after choosing a suitable
> design first) seems to me being far more better than using brute force and
> quick hacks which only means: Only my point of view is right, nothing else
> and my first choice would be programming against any idea which is not
mine.

It seems you've never found yourself in a situation where you *have* to
use a given framework (e.g., MFC) because of corporate policy.

When using such a framework, you may find yourself unable to satisfy
some specs of the system because the framework authors did not provide
the needed 'hooks' in their design. For example, some objects may be
generated inside the framework by directly instantiating a class of the
framework itself, rather than by a flexible factory-pattern that lets you
plug-in your own class for such objects.

If the language in use has allowed (indeed, encouraged) the framework
designers to cast in stone their defective design, your choices are:
-- fork the framework (assuming you can get or reverse-engineer
the sources) -- and commit to spending the next N years of your
life retrofitting new framework releases to your fork, porting the
forked framework to all architectures you must support, etc;
-- resign from your job.

If the language just doesn't allow the framework designers to bind your
hands so tightly, you still have both of these choices if they appeal to
you. You also have others, which *don't* mean "only my point of
view is right" -- they DO mean "I know this darned specific concrete
class they're instantiating cannot do the job I *HAVE* to do, so I'll
have them instantiate another instead" -- just as with a fork, but
without anywhere like as many hassles.

If you've always had free rein in choosing the frameworks you are to
work with, you're in a very unusual situation in this industry. And
the omniscience problem is then just shifted from the frameworks'
designers to you -- once you have coded tens of thousands of lines
to that framework, which instantiates that particular concrete class
in such-and-such situation, what do you do when you THEN find out
that in release N+1 of your program you absoutely need _another_
class for those generated objects? You basically have the above
choices plus (in theory) that of throwing everything you have away
and recoding it all from scratch (supposing you can find a different
framework that will meet your every need forever and ever... yeah,
right, not too bad, although I think that, as fables go, Rapunzel is
far more realistic -- she COULD have unusually strong hair...).


Alex

Paul Rubin

unread,
Aug 19, 2001, 3:23:17 PM8/19/01
to
Bernd.N...@t-online.de (Bernd Nawothnig) writes:
> Access restriction should never be used to arbitrarily prevent a user from
> performing a task. The only idea behind restriction is to hide internal
> details for having more stable code.

That ignores a whole class of applications which run potentially
malicious code, such as mobile code. If Visual Basic had good access
restriction features, we might not see nearly so many computer viruses
spreading through MS Outlook and Word documents.

Frederic Giacometti

unread,
Aug 19, 2001, 5:39:16 PM8/19/01
to

"Michael Ströder" <mic...@stroeder.com> wrote in message
news:3B7E5390...@stroeder.com...

And what about other definitions in the module global scope (classes,
functions...) ? Be consistent :))

Phython's name scoping rules and the import mechanisms make it that changing
the a reference in another module can't happen accidentaly.

Since I bet you won't agree, you'll quickly give a counter exemple proving
I'm wrong...

FG


Bernd Nawothnig

unread,
Aug 19, 2001, 7:05:51 PM8/19/01
to

Everthing of worth has to be sacrificed to prevent M$ from taking world
dominion and it's catastrophic impact? The real problem is a program like
OjE which allows such viruses to work. Otherwise nobody would even see this
'problem'.

I don't know a virus which can infect my newsreader slrn (open source) - it
should be simply not possible to write one. And this restriction makes
obviously sense. It should not be possible for an article (or an email) to
do anything harmfull. And this will only work if the author has the will
(and the ability) to forbid it. Strictly. Ok, in case of this word documents
you have to do nothing but _not_ to be so highly foolish as M$ to allow such
a mechanism to work. These people integrate an interpreter and let him say:
"Welcome my dear unknown code - what shall I do for You?" - unbelievable.

Bernd

Bernd Nawothnig

unread,
Aug 19, 2001, 7:05:58 PM8/19/01
to
On Sun, 19 Aug 2001 21:00:34 +0200, Alex Martelli <ale...@yahoo.com> wrote:

>>>> Hear, hear! Designers aren't omniscient

>> They are not omniscient but they should have visions. And accepting these
>> visions and live and work with them (of course after choosing a suitable
>> design first) seems to me being far more better than using brute force
>> and quick hacks which only means: Only my point of view is right, nothing
>> else and my first choice would be programming against any idea which is
>> not mine.

> It seems you've never found yourself in a situation where you *have* to

> use a given framework (e.g., MFC) because of corporate policy. [...]

I am in such a situation *g* I have to use Python together with PostgreSQL.
This is what i *have* to do but it would be stupid for me to see it as a
restriction in the negative sense. We are searching together for a suitable
framework and if one has an objection it is heard to i.e. nothing is
happening above our heads.

I don't want to start a religious war but i deeply believe that such policy
you have described above will lead into agony on long terms. It means the
death of every dynamic developement process which needs some freedom of
choice and the freedom of information. If you have this guaranteed it would
be easy for you to accept 'open' restrictions. Open because you can look
into the source code and hopefully understand the reasons for the
restrictions - or change it. Nothing is created for eternity :-)

The general goals in designing a new programming language should not mainly
be oriented to work in such unfree environments.

This is my point of view but - as i said above - we should avoid a religious
flame war about open source. I'm new to this NG (and new to Python too) and
mainly interested in Python related things :-)

BTW: this all does _not_ mean that i'm deeply missing private and protected
in Python.

> If you've always had free rein in choosing the frameworks you are to work
> with, you're in a very unusual situation in this industry.

Nobody is totally free and it is not necessary to have the freedom to choose
the framework by yourself but to have the possibility to change things you
can't live with. And there must be a good feeling in general.

That's enough - for me :-)

> And the omniscience problem is then just shifted from the frameworks'
> designers to you

In this special case: yes

> -- once you have coded tens of thousands of lines to that framework, which
> instantiates that particular concrete class in such-and-such situation,
> what do you do when you THEN find out that in release N+1 of your program
> you absoutely need _another_ class for those generated objects?

Crying: "Shit!" - what else? *gg*

But seriously: First I will have to accept that something went wrong with my
ideas. And then i would try to redesign the whole thing avoiding as much
ugly quickhacks as possible.

> You basically have the above choices plus (in theory) that of throwing
> everything you have away and recoding it all from scratch

'mercilessly refactoring' was the keyword ... But it is a big difference
stucking deep into the problem and writing all from scratch knowing
basically nothing. At the point you described _many_ code fragments are
written in your head before you start. Not so if you are unexperienced. We
had this discussion a few days ago. One told me he had lost a floppy disc
with all his source code a few years ago (no back up - of course :-). He
needed months to write the code first but only days to do the work again.
And the second version was better than the lost one.

Hmm, one should delete all of his source code some times :-)

Bernd

Paul Rubin

unread,
Aug 19, 2001, 11:19:47 PM8/19/01
to
Bernd.N...@t-online.de (Bernd Nawothnig) writes:
> > That ignores a whole class of applications which run potentially malicious
> > code, such as mobile code. If Visual Basic had good access restriction
> > features, we might not see nearly so many computer viruses spreading
> > through MS Outlook and Word documents
>
> Everthing of worth has to be sacrificed to prevent M$ from taking world
> dominion and it's catastrophic impact? The real problem is a program like
> OjE which allows such viruses to work. Otherwise nobody would even see this
> 'problem'.

I can't make any sense of what you're saying here. But a little
reality: millions of web pages out there have Javascript on them that
isn't easily able to take over the client machine. Python is
advertised as an embeddable script language and Guido's language
comparison essay explicitly compares it favorably to javascript. If
javascript is useable in important situations where Python can't be
used, Python isn't meeting its advertised goals.

Alex Martelli

unread,
Aug 20, 2001, 5:09:13 AM8/20/01
to
"Bernd Nawothnig" <Bernd.N...@t-online.de> wrote in message
news:slrn9o0fte.3vvilp...@Asterix.t-online.de...
...

> > It seems you've never found yourself in a situation where you *have* to
> > use a given framework (e.g., MFC) because of corporate policy. [...]
...

> I don't want to start a religious war but i deeply believe that such
policy
> you have described above will lead into agony on long terms. It means the

I think this is a serious overbid. When a firm has accumulated a capital
of software projects that interoperate by being all based on the same
framework, it is quite a reasonable policy to say that other projects in
the suite must also use the same framework to ensure continued
interoperation. Software must be maintained, and it would be very
costly to ask each new software maintainer to be or become familiar
with several different frameworks that do roughly the same job.

> death of every dynamic developement process which needs some freedom of
> choice and the freedom of information. If you have this guaranteed it
would
> be easy for you to accept 'open' restrictions. Open because you can look
> into the source code and hopefully understand the reasons for the
> restrictions - or change it. Nothing is created for eternity :-)

Changing the framework you use, whether you call it "forking" or
otherwise, is one of the costliest errors you can make in production
software development. The sources of MFC are available to any
purchaser of Microsoft VC++, which comes bundled with them --
when you find and fix outright bugs you're welcome to submit
the patches to the maintainer. Whether they'll be accepted is of
course another issue, just as it would be for a free or open-source
project. An *architectural limitation*, a DESIGN bug if you will,
is not normally treated in the same way -- again you can suggest
a deep redesign and refactoring, but your chances to get it
accepted by the framework maintainers are slimmer.

When your changes are rejected, you're at a crossroads. Either
you fork the project (my advice: *DON'T*!), or you find other
solutions. Some languages are too rigid to admit of other
solutions -- others give you a chance to survive even in these
dire straits. I prefer the latter.

> The general goals in designing a new programming language should not
mainly
> be oriented to work in such unfree environments.

Free or unfree has little to do with the case. Even if you do have
sources, and therefore implicitly the ability to fork, it's WAY
better not to.

> This is my point of view but - as i said above - we should avoid a
religious
> flame war about open source. I'm new to this NG (and new to Python too)
and
> mainly interested in Python related things :-)

Me too, and one of the many Python related things that interest
me is that it is one of the languages that provide a way to solve
such problems without forking, by having the 'restrictions' of
information-hiding &c be 'advisory' (except of course for the
special case of restricted-execution, where introspection &c are
curtailed to keep untrusted code in its place).


> > If you've always had free rein in choosing the frameworks you are to
work
> > with, you're in a very unusual situation in this industry.
>
> Nobody is totally free and it is not necessary to have the freedom to
choose
> the framework by yourself but to have the possibility to change things you
> can't live with. And there must be a good feeling in general.

A language that limits your "possibility to change things" to forking
the framework is simply less practical than one which, besides of
course allowing that, ALSO lets you dynamically work around problems
on an as-needed, when-needed, if-needed, on-the-fly basis.

I'm not saying it's *pleasant* to, e.g., go and optionally switch a
factory function used deep in the bowels of a framework -- but it
IS one more option you have to save your skin in emergencies.
Making the language more complicated, by enforcing visibility
and accessibility restrictions, to TAKE AWAY that option for the
sake of abstract principles would be an absurd policy.


> > -- once you have coded tens of thousands of lines to that framework,
which
> > instantiates that particular concrete class in such-and-such situation,
> > what do you do when you THEN find out that in release N+1 of your
program
> > you absoutely need _another_ class for those generated objects?
>
> Crying: "Shit!" - what else? *gg*
>
> But seriously: First I will have to accept that something went wrong with
my
> ideas. And then i would try to redesign the whole thing avoiding as much
> ugly quickhacks as possible.

Very nice, and very theoretical. On one side, you have a "ugly quickhack":

toolbarClass = theFramework.FrameWindow.Toolbar
class MyToolbar(toolbarClass):
def minimize(self): pass # workaround toolbar-minimization
bug
theFramework.FrameWindow.Toolbar = MyToolbar

# add a few more lines to make this conditional, potentially
# restore the original toolbarClass at need, etc, etc.

taking about 2 minutes to design, implement and test for somebody who's
deeply familiar with the framework. On the other side, you have before
yourself an open-ended rearchitecturing effort: we can't use any more ANY
of the code pathways in the framework that end up instantiating the
hard-coded concrete class theFramework.FrameWindow.Toolbar, and must
duplicate them ALL in order to ensure they instantiate our MyToolbar
instead. If the framework is in a language which allows the designer
to specify (maybe even as the DEFAULT...) that minimize is not virtual,
the amount of work increases yet more.

All that 'goes wrong', say, is that the framework's designers rigidly
imposed the instantiation of toolbars which inevitably minimize when
their owning frame-window minimizes -- and you need (the UI experts
specify that, and it's non-negotiable) toolbars that don't behave this
way, period. ONE tiny detail out of many thousands you (and the
framework) are dealing with. How much price in terms of language
complexity are you willing to pay in order to ensure your situation
is insoluble except by redesigning everything from scratch, so that
you're *forced* to "Do the Right Thing"?


> > You basically have the above choices plus (in theory) that of throwing
> > everything you have away and recoding it all from scratch
>
> 'mercilessly refactoring' was the keyword ...

I have no problem with that, but it doesn't apply to components,
libraries, or whole frameworks you're re-using. If you touch even
one source-line of that code, you're not re-using any more, you're
forking -- a completely different game.

You can and should refactor the code that your organization
develops and maintains. If a language doesn't enforce (but
just sets as advisory) the limits of information-hiding &c, then
you can, reasonably easily, make the code you develop and
maintain affect some small but crucial aspect of the working
of the framework/library/component, WITHOUT forcing that
reused code. If you choose to use a language that does the
enforcement, you don't have that option any more.

> But it is a big difference
> stucking deep into the problem and writing all from scratch knowing
> basically nothing. At the point you described _many_ code fragments are
> written in your head before you start. Not so if you are unexperienced. We
> had this discussion a few days ago. One told me he had lost a floppy disc
> with all his source code a few years ago (no back up - of course :-). He
> needed months to write the code first but only days to do the work again.
> And the second version was better than the lost one.

Yes, a similar thing happened to me back when I was writing my
thesis, over 20 years ago -- a crash in the experimental computer
system being installed at our university took with it all of our
sources (well, we did have print-outs, as we mostly worked on
teletype-like terminals -- but no backups as the tape units were
not installed yet), so we had to rewrite it (again: we had already
developed half the programs in APL, then had to recode them in
Fortran and assembler as the new experimental computer, a VAX,
didn't have an APL implementation).

Yes, the resulting code does get developed faster and with
better quality than the first time around, at least if the first
time is still reasonably fresh in your mind. It still meant we
graduated in the summer session rather than in the previous
spring session, though -- meaning one more year of tuition
fees the way things worked here at the time, by the way
(we did recoup those, and then some, as the thesis won a
generous cash grant for its quality, admittedly:-).


> Hmm, one should delete all of his source code some times :-)

Maybe if you're 20 to 25. When over 40, you start to see
there are more things you'd like to code, than time left in
your probable remaining life to code them, so the prospect
of redoing stuff you have already done is less appealing.

And if a limitation is in the framework you're using, and that
you have to keep using, and your chosen language _enforces_
information-hiding measures, your rewrite to workaround that
limitation is going to be an unsatisfactory duplication of much
of your framework -- not much better than a fork, in some
respects. Why anybody would complicate a language to
ensure such unpleasantness is really a mystery to me.


Alex

Tim Rowe

unread,
Sep 9, 2001, 1:48:00 PM9/9/01
to
In article <7xsneoi...@ruckus.brouhaha.com>, phr-...@nightsong.com
(Paul Rubin) wrote:

I don't much believe in general purpose languages. The trouble is, a
language that can do everything won't be very good at anything. Be aware
of the strengths and weaknesses of different languages, have more than one
string to your bow, and know how to choose which one to use. I doubt if
Python could ever be the language of choice for real-time operating system
design, embedded control or safety critical for instance, and should
resist adding complication in an attempt to move into those fields. IMHO
Python development should play to its strengths and not try to turn it
simultaneously into Haskell, Ada, Forth, C++ and Smalltalk!

0 new messages