无法通过管道命令访问 django shell 中的导入函数?

sih*_*og5 2 python django shell

这是一个python脚本tshi3.py

    import csv
    def li2ho2():
        print(csv)
    li2ho2()
Run Code Online (Sandbox Code Playgroud)

我复制了这段代码并将其粘贴到python manage.py shell. 有用。

但我跑了python manage.py shell < tshi3.py。得到了NameError: name 'csv' is not defined

为什么?

环境:

    Linux Mint 18.1
    Python 3.4.1 (default, Sep  3 2014, 08:45:22) 
    Django==1.11.4
Run Code Online (Sandbox Code Playgroud)

一个类似的问题

小智 5

我已经查看了shell命令代码。这里是:

if sys.platform != 'win32' and select.select([sys.stdin], [], [], 0)[0]:
    exec(sys.stdin.read())
    return
Run Code Online (Sandbox Code Playgroud)

问题出在没有传递globalsandlocals参数的情况下调用 exec 命令,那么默认情况下,将使用当前作用域的globals()andlocals()字典。

请记住,在模块级别, globals 和 locals 是同一个字典,但在当前范围(在 django.core.management.commands.shell.Command.handle 处), globals() 和 locals() 是两个不同的字典。现在,当tshi3.py执行的代码时,事情变得无法控制。

让我们来看看每一行代码:

import csv
Run Code Online (Sandbox Code Playgroud)

这将导入模块csv并将其放入locals()字典中。因此,如果locals()dict与dict 相同globals(),则这也将在globals()dict 中。但是,在我们的例子中,csv只在locals()字典中,globals()不在字典中。

下一个:

def li2ho2():
    print(csv)
Run Code Online (Sandbox Code Playgroud)

当命令print(csv)被调用时,csvlocals()在函数的字典中查找li2ho2,它肯定不存在,所以csvglobals()字典中查找。但是正如我上面写的那样,csv不在globals()字典中,这就是错误:NameError: name 'csv' is not defined引发的原因。

我尝试更改 tshi3.py 的代码如下:

import csv

print('globals() equals to locals(): {}'.format(globals() == locals()))
print('csv is in globals(): {}'.format('csv' in globals()))
print('csv is in locals(): {}'.format('csv' in locals()))

def li2ho2():
    print('inside li2ho2 function:')
    print('    csv is in globals(): {}'.format('csv' in globals()))
    print('    csv is in locals(): {}'.format('csv' in locals()))

li2ho2()
Run Code Online (Sandbox Code Playgroud)

并以两种不同的方式运行它:

$ python tshi3.py 
globals() equals to locals(): True
csv is in globals(): True
csv is in locals(): True
inside li2ho2 function:
    csv is in globals(): True
    csv is in locals(): False

$ ./manage.py shell < tshi3.py 
globals() equals to locals(): False
csv is in globals(): False
csv is in locals(): True
inside li2ho2 function:
    csv is in globals(): False
    csv is in locals(): False
Run Code Online (Sandbox Code Playgroud)

所以,你可以看到它和我上面解释的完全一样。这个问题可以通过传递一个空字典作为命令的globals参数来解决exec,如下所示:

exec(sys.stdin.read(), {})

希望这对您有所帮助,我很抱歉无法更简短地解释问题。


Iur*_*eev 5

正如这里所说的-manage.py shell命令分割globals()和locals()。因此,如果您需要变量可见性的预期行为,您应该使用新导入的局部变量手动更新全局变量列表。下面的方法比更改manage.py shell函数更容易:

import csv

globals().update(locals())

def li2ho2():
    print(csv)

li2ho2()
Run Code Online (Sandbox Code Playgroud)