colorama
colorama copied to clipboard
Handle multiple calls to init() and deinit() properly
Looking at this code: https://github.com/tartley/colorama/blob/master/colorama/initialise.py#L23
It looks like the code currently doesn't properly handle calling init()
multiple times, I'd expect the init()
function to set some internal state to know that it is already inited (maybe with a counter, in case nested init()
/deinit()
pairs should be supported?). Same with calling deinit()
, it doesn't seem to always restore things properly.
Example code:
import colorama
colorama.init()
colorama.init()
colorama.deinit()
(of course, it might not be that obvious, but imagine two libraries want to initialize colorama in some situations)
Maybe it should also support nested init()
/deinit()
pairs:
import colorama
colorama.init() # Initialized now
colorama.init() # Still initialized, maybe increase "refcount"/"initcount"
colorama.deinit() # Still initialized, because init was called twice
colorama.deinit() # Actually deinitialize, as the "refcount"/"initcount" will go to zero
Similar logic probably applies to reinit()
, not sure.
I'm using colorama 0.3.9 with python 2.7.6 (32-bit) on win10 64-bit, and for some reason I have to call colorama.init() twice in a row to get colors to actually work; if I only call it once, then the color codes get literally displayed rather than the colors actually changing. So that probably needs to be understood and fixed before you go changing the behavior of consecutive calls to colorama.init().
To @thp, Nov 2, 2018
- So, what is your solution for making
deinit()
work? - What are 'refinit' and 'initcount'? I couldn't find them anywhere.
Something like that (assuming thread safety is not an issue, otherwise protect it with threading.Lock
):
# The original init function
def real_init():
...
# The original deinit function
def real_deinit():
...
_init_counter = 0
def init():
global _init_counter
if _init_counter == 0:
real_init()
_init_counter += 1
def deinit():
global _init_counter
_init_counter -= 1
assert _init_counter >= 0, 'deinit() called without calling init()'
if _init_counter == 0:
real_deinit()
real_init
@thp, thank you. I patched 'initialised.py' as you suggested and run the following test :
print "Start ID",id(sys.stdout) # 20500600
colorama.init()
print "ID after init 1",id(sys.stdout) # 25212144
colorama.init()
print "ID after init 2",id(sys.stdout) # 25212144
colorama.deinit()
print "ID after deinit 1",id(sys.stdout) # = 25212144
try:
colorama.deinit() # Not accepted
print "ID after deinit 2",id(sys.stdout)
colorama.deinit()
print "ID after deinit 3",id(sys.stdout)
except:
pass
The differences from the test with the original 'initialise.py', and as you can see, are the following:
- A second
init()
call does not change the stdout ID (from the first call) - Only one
deinit()
call is allowed (the next one throws en exception). - This single
deinit()
call does not restore the original stdout ID! It is as if it is ignored.
Note: After posting the above reply, I tried another test: I called init()
once only and then deinit()
. Guess what: The deinit()
call threw an exception!
Anyway, why should we care to use deinit()
at all. I never do it and never had a problem. Is there perhaps a hidden problem that it's not good for the system?
Possibly a duplication of issue #145.
I did a wrapper on colorama in order to make a customized logger
For some reason calling .init()
straight ahead performs worst than calling .deinit()
first and then .init()