_GLOBAL_DEFAULT_TIMEOUT in socket.py

In python 2.6, the timeout attribute of the socket from various higher level modules (like urllib2) is passed as socket._GLOBAL_DEFAULT_TIMEOUT.
If you look at socket.py in Lib, you will find that

_GLOBAL_DEFAULT_TIMEOUT = object()


a) This kind of a construct was new to me, why should _GLOBAL_DEFAULT_TIMEOUT be set to an object() than say None.

Update: Because None for a timeout is a special value that would set the socket in blocking mode. That is the reason None is not used.

b) If this is just for a global value holding, why not just


global _GLOBAL_DEFAULT_TIMEOUT



Here is my understanding, the reason for having _GLOBAL_DEFAULT_TIMEOUT is to have a global default timeout value that can be accessible via various application layer modules (like ftplib, httplib, urllib).

Update: Correct

But the default value of the timeout is written at the lower layer socket module and is returned by
socket.getdefaulttimeout()
and may be set via socket.setdefaulttimeout or via timeout parameters at the application opening functions (like urllib2.urlopen('url',timeout=42).


Update: So what?. Wrong.


Get socket.getdefaulttimeout() is implemented in C; and to be preserve the value between C methods and the python library methods, an object() would be essential instead of a global.

object() might essentially provide an address location for the variable which would be global.


Am I confused? The way the C implementation works is the value is set to a global variable inside of C and its accessed by interfaces like getdefaulttime and setdefaulttime.

Nothing to maintain global values between Python and modules written in C. Are they sharable? I dont know.

This kind of construct is used to have a object to maintain a global state.

global myobj is just a declaration to the compiler that it is global. declared somewhere else and start using the same value. It is not setting things or even defining for the myobj to be used as global. OKay?


a = 100
print id(a)

def foo():
global a
print a, id(a)

foo()



[12:17:45 senthil]$python a1.py
23379248
100 23379248


So, in effect:

_GLOBAL_DEFAULT_TIMEOUT = object() is a just creating a empty object whose value can be shared.

Thats it and None is not a good option because, None in this case means that socket be a blocking one.


Here are some experimentations with urllib2 and new socket._GLOBAL_DEFAULT_TIMEOUT



Python 2.7a0 (trunk:72879M, May 24 2009, 12:51:19)
[GCC 4.3.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import socket
>>> print socket.getdefaulttimeout()
None
>>> socket.setdefaulttimeout(42)
>>> print socket.getdefaulttimeout()
42.0
>>> import urllib2
>>> obj = urllib2.urlopen("http://www.google.com")
>>> dir(obj)
['__doc__', '__init__', '__iter__', '__module__', '__repr__', 'close', 'code', 'fileno', 'fp', 'getcode', 'geturl', 'headers', 'info', 'msg', 'next', 'read', 'readline', 'readlines', 'url']
>>> dir(obj.fp)
['__class__', '__del__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '_close', '_getclosed', '_rbuf', '_rbufsize', '_sock', '_wbuf', '_wbuf_len', '_wbufsize', 'bufsize', 'close', 'closed', 'default_bufsize', 'fileno', 'flush', 'mode', 'name', 'next', 'read', 'readline', 'readlines', 'softspace', 'write', 'writelines']
>>> dir(obj.fp._sock)
['__doc__', '__init__', '__module__', '_check_close', '_method', '_read_chunked', '_read_status', '_safe_read', 'begin', 'chunk_left', 'chunked', 'close', 'debuglevel', 'fp', 'getheader', 'getheaders', 'isclosed', 'length', 'msg', 'read', 'reason', 'recv', 'status', 'strict', 'version', 'will_close']
>>> dir(obj.fp._sock.fp)
['__class__', '__del__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__iter__', '__module__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', '_close', '_getclosed', '_rbuf', '_rbufsize', '_sock', '_wbuf', '_wbuf_len', '_wbufsize', 'bufsize', 'close', 'closed', 'default_bufsize', 'fileno', 'flush', 'mode', 'name', 'next', 'read', 'readline', 'readlines', 'softspace', 'write', 'writelines']
>>> dir(obj.fp._sock.fp._sock)
['__class__', '__delattr__', '__doc__', '__format__', '__getattribute__', '__hash__', '__init__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'accept', 'bind', 'close', 'connect', 'connect_ex', 'dup', 'family', 'fileno', 'getpeername', 'getsockname', 'getsockopt', 'gettimeout', 'listen', 'makefile', 'proto', 'recv', 'recv_into', 'recvfrom', 'recvfrom_into', 'send', 'sendall', 'sendto', 'setblocking', 'setsockopt', 'settimeout', 'shutdown', 'timeout', 'type']
>>> dir(obj.fp._sock.fp._sock.gettimeout)
['__call__', '__class__', '__cmp__', '__delattr__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__self__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__']
>>> print(obj.fp._sock.fp._sock.gettimeout)

>>> print(obj.fp._sock.fp._sock.gettimeout())
42.0

2 comments:

Unknown said...

Thanks for the explanation of defult time out. I'm running a long python job that last for a few days and it quits automatically after a day. I'm wondering if this glocal default timeout is causing the issue ... why 42? is it in hour unit? Or just some random number that you pick?
Jing

iamnoone said...

@cyanpku : as to "why 42", you may want to google for "life, the universe and everything".