[Tutor] PYTHONHASHSEED, -R

Albert-Jan Roskam fomcl at yahoo.com
Mon Jul 29 23:27:24 CEST 2013


----- Original Message -----

> From: eryksun <eryksun at gmail.com>
> To: Albert-Jan Roskam <fomcl at yahoo.com>
> Cc: Python Mailing List <tutor at python.org>
> Sent: Monday, July 29, 2013 7:44 PM
> Subject: Re: [Tutor] PYTHONHASHSEED, -R
> 
>>  question is almost new-thread-worthy, but: if I would like to make
>>  my app work for 2.x and 3.x, what is the best approach:
>>  (a) use "if sys.version_info.major...." throughout the code
>>  (b) use 2to3, hope for the best and fix manually whatever can't be 
> fixed
> 
> (c) Use "six".

Ok, thanks, I will check this out. Btw, is Pythonbrew still the preferred way of working with different python versions? I read about it and it seems to be handy to use it to switch between versions. But I also read it is no longer maintained.

> BTW, sys.version_info.major doesn't work in <2.7. The names were added
> in 2.7/3.1.
> 
>>>  The dict isn't changing state,
>> 
>>  So that's the criterion! Thanks! So as long as you don't use
>>  __setitem__ and __delitem__ (maybe also __setattribute__,
>>  __delattribute__, ...) the state does not change.
> 
> It's __getattribute__, __getattr__, __setattr__ and __delattr__. I
> guess that's relevant if we're talking about a dict that's 
> functioning
> as a namespace, but that's a bit meta. Setting attributes on the dict
> itself (I guess it's a subclass we're talking about; normal dict
> instances don't have a dict) wouldn't affect the hash table it uses
> for the contained items.
> 
> BTW, these slot wrappers generally aren't called in CPython, not
> unless you're overriding the built-in slot function. They're a hook
> back into the C API. They bind as a method-wrapper that has a function
> pointer to a C wrapper function that calls the C slot function.
> 
> If you override __setattr__, your type's tp_setattro slot is set to
> slot_tp_setattro, which gets called by PyObject_SetAttr. If the value
> being 'set' is NULL, this function looks up "__delattr__" in 
> your
> type. Since you didn't override this, it finds and binds the
> __delattr__ slot wrapper from your base class(es).
> 
> This is also comes up with rich comparison functions, for which all 6
> comparisons are handled by the single slot function, tp_richcompare.
> So if you subclass dict and override __lt__, then slot_tp_richcompare
> finds the slot wrapper for the other 5 comparisons by searching dict's
> dict:
> 
>     >>> type(vars(dict)['__gt__'])
>     <type 'wrapper_descriptor'>
> 
> And binds it to the instance as a method-wrapper:
> 
>     >>> type(vars(dict)['__gt__'].__get__({}))
>     <type 'method-wrapper'>
> 
> After jumping through several hoops it ends up at dict_richcompare.
> For a regular dict, PyObject_RichCompare simply jumps straight to
> dict_richcompare. It doesn't use the slot wrapper.
> 
>>>      Keys and values are iterated over in an arbitrary order which is
>>>      non-random,
>> 
>>  That sounds like a contradictio in terminis to me. How can something
>>  be non-random and arbitrary at the same time?
> 
> It's just worded generally to be valid for all implementations. They
> could have gone into the specifics of the open-addressing hash table
> used by CPython's dict type, but it would have to be highlighted as an
> implementation detail. Anyway, the table has a history (collisions
> with other keys, dummy keys) and size that affects the insertion
> order. It isn't ontologically random; it's contingent. But that's
> getting too philosophical I think.
> 
>>>  CPython 3.3 defaults to enabling hash randomization. Set the
>>>  environment variable PYTHONHASHSEED=0 to disable it.
>> 
>>  So in addition to my "2to3" question from above, it might be a 
> good
>>  idea to already set PYTHONHASHSEED so Python 2.x behaves like
>>  Python 3.x in this respect, right? Given that the environment
>>  variables are already loaded once Python has started, what would be
>>  the approach to test this? Call os.putenv("PYTHONHASHSEED", 1), 
> and
>>  then run the tests in a subprocess (that would know about the
>>  changed environment variables)?
> 
> Sorry, I don't see the point of this. PYTHONHASHSEED is to be set by a
> system administrator as a security measure. I think CPython is the
> only implementation that has this feature.

I was referring to what is at the bottom of this page (and I believe it's also mentioned in the doctest documentation):
http://python3porting.com/problems.html
Basically setting PYTHONHASHSEED will help you find doctests that are badly written, even prior to Python 3.3, but from 3.3 onwards they will fail no matter what. I hope I am not too vague now ;-)

> With regard to tests that depend on the PYTHON* environment variables,
> Python's own tests use subprocess.Popen to run sys.executable with a
> modified "env" environment (e.g. checking the effect of
> PYTHONIOENCODING).

Ah, ok, glad to read that this is also sort of what I had in mind.


More information about the Tutor mailing list