Python 3.4, sem acesso a uma variável criada com exec ()

Com o Python 3.4 e em uma função, este pedaço de código aparece:

ch0 = 'dico[\''+ ans +'\']' # dico is a dictionary and ans is a key of this dictionary

print('test')
print(list(locals()))

exec('keys2 = list(' + ch0 + ')', locals())

print(list(locals()))
print(locals()['keys2'])

print('keys2:', keys2)

Esta é a saída:

test
['dico', 'save', 'keys0', 'LOG_FILENAME', 'ch0', 'flag', 'completer', 'k', 'ans', 'keys1']
['dico', 'save', 'keys0', 'LOG_FILENAME', 'ch0', 'flag', 'completer', 'k', 'ans', 'keys1', '__builtins__', 'keys2']
['General informations', 'Experiments parameters', 'Calculated parameters']
Traceback (most recent call last):
  File "/data_1/dataGestion.py", line 189, in consult_db
    print('keys2:', keys2)
NameError: name 'keys2' is not defined

Como esperado, observamos a criação da variável keys2 no escopo local, e essa variável contém bem os valores esperados (['Informações gerais', 'Parâmetros de experimentos', 'Parâmetros calculados']), como parece indicar o dicionário retornado pelos habitantes locais. () Mas não é possível acessar essa variável keys2 (o nome 'keys2' não está definido !!!!). Por quê ?

EDIT 1: Vimos que Keys2 está no escopo local porque no código da pergunta acima:

print(list(locals()))

e

print(locals()['keys2'])

Retorna:

['dico', 'keys0', 'save', 'k', 'ans', 'keys1', '__builtins__', 'flag', 'LOG_FILENAME', 'keys2', 'ch0', 'completer']
['General informations', 'Experiments parameters', 'Calculated parameters']

MAS !!! porque se eu alterar o código acima com:

ch0 = 'dico[\''+ ans +'\']' # dico is a dictionary and ans is a key of this dictionary
print('test')

exec('keys2 = list(' + ch0 + ')', locals())

keys2 = locals()['keys2']

print('keys2:', keys2)

A variável keys2 não é criada, como podemos ver novamente com a exceção NameError gerada:

Traceback (most recent call last):
  File "/data_1/IRM/amigo/src/IRMAGE_python_modules/IRMAGE_dataGestion.py", line 191, in consult_db
    print('keys2:', keys2)
NameError: name 'keys2' is not defined

EDIT 2: Continuando a jogar com exec () e locais () ... Considera o seguinte código:

ch0 = 'dico[\''+ ans +'\']' # dico is a dictionary and ans is a key of this dictionary
print('test')

namespace = locals()

print(list(namespace))
print(list(locals()))
print(list(globals()))

exec('keys2 = list(' + ch0 + ')', namespace)

keys2 = namespace['keys2']
print()

print(list(namespace))
print(list(locals()))
print(list(globals()))

print('keys2:', keys2)

A saída é:

test
['ch0', 'ans', 'completer', 'save', 'keys0', 'keys1', 'k', 'flag', 'dico', 'LOG_FILENAME']
['ch0', 'ans', 'completer', 'save', 'keys0', 'keys1', 'k', 'flag', 'dico', 'LOG_FILENAME', 'namespace']
['__spec__', 'nbLigne', 'remove', 'listdir', 'getSampleStyleSheet', 'Paragraph', '__builtins__', 'system', 'upvivification', '__package__', 'exit', '__doc__', 'AutoVivification', 'recupParameter', 'verSofts', 'logging', 'revivification', 'renameComment', 'unvivification', 'creatExpParameter', 'rlcompleter', 'consult_db', 'makedirs', 'datetime', 'isdir', 'recupCover', 'MyCompleter', 'verifFichier', 'dico2txt', 'para2dic', 'readlineComp', '__name__', '__file__', 'anonym', '__cached__', '__loader__']

['ch0', 'ans', 'completer', 'save', 'keys0', 'keys1', 'k', 'flag', 'dico', 'LOG_FILENAME', 'namespace', '__builtins__', 'keys2']
['ch0', 'ans', 'completer', 'save', 'keys0', 'keys1', 'k', 'flag', 'dico', 'LOG_FILENAME', 'namespace', '__builtins__', 'keys2']
['__spec__', 'nbLigne', 'remove', 'listdir', 'getSampleStyleSheet', 'Paragraph', '__builtins__', 'system', 'upvivification', '__package__', 'exit', '__doc__', 'AutoVivification', 'recupParameter', 'verSofts', 'logging', 'revivification', 'renameComment', 'unvivification', 'creatExpParameter', 'rlcompleter', 'consult_db', 'makedirs', 'datetime', 'isdir', 'recupCover', 'MyCompleter', 'verifFichier', 'dico2txt', 'para2dic', 'readlineComp', '__name__', '__file__', 'anonym', '__cached__', '__loader__']
keys2: ['Calculated parameters', 'General informations', 'Experiments parameters']

Com esse resultado, entendo que o dicionário (namespace) passado como argumento com exec () é usado para encontrar as variáveis no escopo da função exec (), mas também este dicionário (namespace) contém todas as variáveis criadas após a execução de exec (). Isso é compreendido, mas ainda não sublinhei por que, na EDIT 1, keys2 = locals () ['keys2'] não está funcionando enquanto keys2 = namespace ['keys2'] está funcionando neste EDIT 2?

EDIT 3: Continuando a jogar com exec () e locais () ... Considera o seguinte trecho de código:

ch0 = 'dico[\''+ ans +'\']' # dico is a dictionary and ans is a key of this dictionary
print('test')

print(list(locals()))
print(list(globals()))

exec("global keys2; keys2 = list(" + ch0 + "); print('\\n** keys2 inside exec function: {}'.format(keys2))", locals())

print()

print(list(locals()))
print(list(globals()))

print('keys2:', keys2)

A saída é:

test
['ch0', 'LOG_FILENAME', 'k', 'flag', 'save', 'ans', 'keys0', 'dico', 'completer', 'keys1']
['recupCover', 'MyCompleter', '__name__', 'para2dic', 'readlineComp', 'upvivification', 'listdir', 'verifFichier', 'recupParameter', 'system', 'remove', '__doc__', 'nbLigne', 'renameComment', '__spec__', '__file__', 'anonym', 'creatExpParameter', '__package__', 'isdir', 'revivification', 'exit', '__loader__', 'makedirs', 'datetime', 'consult_db', 'Paragraph', '__cached__', '__builtins__', 'AutoVivification', 'getSampleStyleSheet', 'unvivification', 'rlcompleter', 'logging', 'verSofts', 'dico2txt']

** keys2 inside exec function: ['Experiments parameters', 'Calculated parameters', 'General informations']

['ch0', 'LOG_FILENAME', 'k', 'flag', 'save', 'ans', 'keys0', 'dico', 'completer', 'keys1', '__builtins__', 'keys2']
['recupCover', 'MyCompleter', '__name__', 'para2dic', 'readlineComp', 'upvivification', 'listdir', 'verifFichier', 'recupParameter', 'system', 'remove', '__doc__', 'nbLigne', 'renameComment', '__spec__', '__file__', 'anonym', 'creatExpParameter', '__package__', 'isdir', 'revivification', 'exit', '__loader__', 'makedirs', 'datetime', 'consult_db', 'Paragraph', '__cached__', '__builtins__', 'AutoVivification', 'getSampleStyleSheet', 'unvivification', 'rlcompleter', 'logging', 'verSofts', 'dico2txt']
Traceback (most recent call last):
  File "/data_1/IRM/amigo/src/IRMAGE_python_modules/IRMAGE_dataGestion.py", line 206, in consult_db
    print('keys2:', keys2)
NameError: name 'keys2' is not defined

Então ... mesmo se definirmos keys2 como uma variável global na função exec (), ela não estará no escopo global, pois retornará os globais () após a função exec () ... Confesso que algumas coisas sentem minha falta. ..

questionAnswers(1)

yourAnswerToTheQuestion