[Python] Strano comportamento del comando shell di Django.

Paolo Leggio paolo a digitalmonkeys.it
Mar 17 Set 2019 15:44:28 CEST


Ciao a tutti, un piccolo rompicapo.
quando eseguo il comando shell di Django, ho un comportamento inaspettato dell' interprete python che proprio non riesco a spiegare:


Questo é il semplice snippet di codice che voglio eseguire:
Quando tento l’escussione con python  manage.py shell < test.py  ottengo un errore e non riesco a capire a che modulo python vengono associate le funzioni definite.

File test.py
def foo():
    print('foo() --start--')
    print('foo() --stop--')

def bar():
    print('bar() --start--')
    print('bar() --stop--')

def main():
    print('main() ### start ###')
    foo()
    bar()
    print('main() ### stop ###')

foo()
bar()
main()
Risultato aspettato:	
foo() --start--
foo() --stop--
bar() --start--
bar() --stop--
main() ### start ###
foo() --start--
foo() --stop--
bar() --start--
bar() --stop--
main() ### stop ###


Se provo a eseguirlo passando il file come stdinput alla shell di Django, qualcosa nella gestione dei moduli non funziona e il codice non gira:
python  manage.py shell < test.py
foo() --start--
foo() --stop--
bar() --start--
bar() --stop--
main() ### start ###
Traceback (most recent call last):
  File "./manage.py", line 21, in <module>
    main()
  File "./manage.py", line 17, in main
    execute_from_command_line(sys.argv)
  File "/private/tmp/test/lib/python3.7/site-packages/django/core/management/__init__.py", line 381, in execute_from_command_line
    utility.execute()
  File "/private/tmp/test/lib/python3.7/site-packages/django/core/management/__init__.py", line 375, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/private/tmp/test/lib/python3.7/site-packages/django/core/management/base.py", line 323, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/private/tmp/test/lib/python3.7/site-packages/django/core/management/base.py", line 364, in execute
    output = self.handle(*args, **options)
  File "/private/tmp/test/lib/python3.7/site-packages/django/core/management/commands/shell.py", line 95, in handle
    exec(source)
  File "<string>", line 17, in <module>
  File "<string>", line 11, in main
NameError: name 'foo' is not defined




Se lo eseguo passandolo com stdinput direttamente a python funziona tutto, le nuove funzioni vengono inserite nel modulo __main__ <module '__main__' (built-in)>
python  < test.py
Il codice del comando shell di Django, é molto semplice:
dopo aver fatto il bootstrap del progetto Django, non fa altro che 
exec(sys.stdin.read())

Provando a mano, 
Se  lancio la shell di Django in modalitá interattiva
python manage.py shell
Metto i sorgenti in una stringa e la eseguo con exec() un po come fa il comando shell, funziona tutto
Python 3.7.4 (default, Sep  7 2019, 18:27:02)
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
>>> source_code = '''
... def foo():
...     print('foo() --start--')
...     print('foo() --stop--')
...
... def bar():
...     print('bar() --start--')
...     print('bar() --stop--')
...
... def main():
...     print('main() ### start ###')
...     foo()
...     bar()
...     print('main() ### stop ###')
...
... foo()
... bar()
... main()
... '''
>>>
>>> exec(source_code)
foo() --start--
foo() --stop--
bar() --start--
bar() --stop--
main() ### start ###
foo() --start--
foo() --stop--
bar() --start--
bar() --stop--
main() ### stop ###
>>>

Cosa succede quando passo nel comando shell di Django?
Ciao a tutti.



-------------- parte successiva --------------
Un allegato HTML è stato rimosso...
URL: <http://lists.python.it/pipermail/python/attachments/20190917/004e205f/attachment.html>


Maggiori informazioni sulla lista Python