[Python-Dev] an alternative to embedding policy in PEP 418

Cameron Simpson cs at zip.com.au
Sat Apr 7 01:11:44 CEST 2012


On 06Apr2012 20:25, Steven D'Aprano <steve at pearwood.info> wrote:
| Cameron Simpson wrote:
| > My core objective was to allow users to query for clocks, and ideally
| > enumerate and inspect all clocks. Without the caller having platform
| > specific knowledge.
| 
| Clocks *are* platform specific -- not just in their availability, but also in 
| the fine details of their semantics and behaviour. I don't think we can or 
| should try to gloss over this.

This is why get_clock() returns a clock object, which can have metadata
exposing such details. Up to and including the name of the platform specific
library/system-call at its core.

The issue with monotonic() on its own is that the guarentees in the doco
will have to be fairly loose. That prevents the user learning about
"fine details of their semantics and behaviour". Glossing over this
stuff is exactly what offering _only_ a few genericly characterised
clock names (monotonic() et al) does.

| If people are making decisions about timers 
| without knowledge of what their platform supports, they're probably making 
| poor decisions. Even the venerable time.time() and time.clock() differ between 
| Linux and Windows.

time.clock() does, as (you?) clearly demonstrated elsewhere.

time.time()? (Aside from precision?)

| > Allowing for the sake of discussion that this is desirable, what would
| > you propose as an API instead of get_clock() (and its friend, get_clocks()
| > for enumeration, that I should stuff into the code).
| 
| The old ways are the best. We don't have math.get_trig() and math.get_trigs() 
| functions for querying trigonometric functions, we just expose the functions 
| directly.
| 
| I think the way to enumerate and inspect all clocks is with the tried and true 
| Python introspection tools that people use on all other functions:
| 
| * use dir(time) to see a list of names available in the module

So, they see "monotonic". Does that tell them much about fine details?

| * use help(time) to read their help

Useful only to humans, not programs.

| * read the Fine Manual to find out more

Useful only to humans, not programs.

| * use try... except... to detect the existence of a clock

Useful only for a fixed list of defined name. Works fine for monotonic,
highres, steady or whatever. And I would be ok with the module
presenting these only where available and concealing them otherwise,
thus raising AttributeError. Or ImportError ("from time import
monotonic").

| There's nothing special about clocks that needs anything more than this.

This I think is false. In fact, I think your own statement at the start
about glossing over fine details goes against this.

If I ask for a highres clock, I might well care _how_ precise it was.

If I ask for a steady clock, I might well care how large its slews were.

If I ask for a monotonic clock, I might well want to know if it tracks
wall clock time (even if by magic) or elapsed system run time (eg time
that stops increasing if the system is suspended, whereas wallclocks do
not). Example: a wallclock is nice for log timestamps. A system run time
clock is nice for profiling. They're both monotonic in some domain.

| get_clock() looks like a factory function, but it actually isn't. It just 
| selects from a small number of pre-existing clocks.

That number may still be a few. Victor's made it clear that Windows
has a choice of possible highres clocks, UNIX clock_getres() offers
several possible clock behaviours and an indication that a platform may
have several clocks embodying a subset of these, and may indeed offer
more clocks.

| We should just expose 
| those pre-existing clocks directly.

But exposing them _purely_ _by_ _name_ means inventing names for every single
platform clock, and knowing those names per platform. time.clock() is a
fine example where the name tells you nearly nothing about the clock
behaviour. If the user cares about fine detail as you suggest they need
to know their platform and have _external_ knowledge of the platform
specifics; they can't inspect from inside the program.

| I don't see any advantage in adding that 
| extra level of indirection or the addition of all this complexity:
| * a function get_clock() to select a clock
| * a function get_clocks() to enumerate all the clocks

These are only two functions because the next alternative seemed an
all_clocks= mode parameter, which changed the signature of the function
return.

Another alternative is the public lists-of-clocks.

The point it to be able to enumerate all available clocks for
consideration of their properties; get_clock() provides a simple way
to coarsely say "a clock like _this_" for the common instances of
"this".

| * another function for querying the properties of a clock

No, that's why you get a clock object back. You can examine it directly
for defined metadata names (epoch, precision, underlying-os-clock-name,
etc). In exactly the fashion you appear to want for the top level
offerings: by knowing the metadata property names.

| All those functions accomplish is to increase the complexity of the API, the 
| documentation and the implementation. It's one more special case for the user 
| to learn:
| 
| "To find out what functions are available, use dir(module), except for clocks, 
| where you have to use time.get_clocks()."

But dir(module) _will_ list monotonic et al anyway, and possibly matching
public clock list names. get_clock() is only for when you want to dig
around more flexibly.

| Another problem with get_clock() -- it will be an attractive nuisance for the 
| sort of person who cares about symmetry and completeness. You will have a 
| steady trickle of "feature requests" from users who are surprised that not 
| every combination of features is supported. Out of the eight or sixteen or 
| thirty-two potential clocks that get_clock() tempts the user with, only three 
| or five will actually exist.

And the optional "clocklist" parameter addresses such feaping creaturism
by providing a hook for _other_ modules to offer a clock list. Such as a
list of syntheic clocks with cool (or insane:-) properties. Without
burdening the time module.

| The only advantage of get_clock is that you don't need to know the *name* of a 
| platform clock in order to use it, you can describe it with a series of flags 
| or enums. But in practice, that's not an advantage, that's actually a 
| disadvantage. Consider:
| 
| "Which clock should I use for such-and-such a task, foo or bar?"

What's your list of foo, bah? Again, I'm not talking about removing
monotonic et al. I'm talking about exposing the alternatives for when
the chosen-by-the-module monotonic doesn't fit.

| versus
| "Which clock should I use for such-and-such a task, get_clock(spam, eggs, 
| cheese) or get_clock(ham, eggs, truffles)?"

One hopes the user knows the task. Then they can specify cheese or
truffles. Again, only if they feel they need to because the bare
monotonic et al don't fit, or was too vague.

| The mere mechanics of talking about these clocks will suffer because they 
| aren't named.

But they _can_ be named! get_clock() is for when you don't know or care
their names, only their behaviours! And also for when an available clock
_wasn't_ one returned by the monotonic et al names.

Cheers,
-- 
Cameron Simpson <cs at zip.com.au> DoD#743
http://www.cskk.ezoshosting.com/cs/

I do not trust thee, Cage from Hell, / The reason why I cannot tell, /
But this I know, and know full well: / I do not trust thee, Cage from Hell.
        - Leigh Ann Hussey, leighann at sybase.com, DoD#5913


More information about the Python-Dev mailing list