python刷新/重新加载

python refresh/reload

这是一个非常基本的问题,但我还没有通过网上搜索找到答案。

我使用python来控制arcgis,我有一个简单的python脚本,它调用一些预先编写的代码。

但是,当我对预先编写的代码进行更改时,似乎不会导致任何更改。我导入了这个模块,并尝试刷新它,但什么也没有发生。

我甚至把它调用的文件移到了另一个位置,脚本仍然可以正常工作。我昨天做的一件事是,我添加了一个文件夹,其中所有的python文件都在sys路径中(使用sys.append("path")),我想知道这是否起了作用。

事先谢谢,对于这个草率的术语感到抱歉。


不清楚"刷新"是什么意思,但python的正常行为是,您需要重新启动软件,以便它重新查看python模块并重新阅读它。

如果重新启动后仍不处理您的更改,则这是由于以下两个错误之一造成的:

  • pyc文件上的时间戳不正确,将来还会有一段时间。
  • 您实际上编辑了错误的文件。
  • 即使不使用reload()命令重新启动软件,也可以使用reload重新读取文件。请注意,任何指向模块中任何内容的变量都需要在重新加载后重新导入。像这样:

    1
    2
    3
    4
    5
    import themodule
    from themodule import AClass

    reload(themodule)
    from themodule import AClass


    一种方法是调用reload

    示例:下面是foo.py的内容:

    1
    2
    def bar():
        return 1

    在交互式会话中,我可以做到:

    1
    2
    3
    >>> import foo
    >>> foo.bar()
    1

    然后在另一个窗口中,我可以将foo.py更改为:

    1
    2
    def bar():
        return"Hello"

    在交互会话中,调用foo.bar()仍然返回1,直到我执行以下操作:

    1
    2
    3
    4
    >>> reload(foo)
    <module 'foo' from 'foo.py'>
    >>> foo.bar()
    'Hello'

    调用reload是一种确保模块是最新的方法,即使磁盘上的文件已更改。它不一定是最有效的(您最好检查文件的最后一次修改时间,或者在您使用reload之前使用pyinotify),但它确实可以快速实现。

    python不每次都从源模块读取的一个原因是加载一个模块(相对)比较昂贵——如果您有一个300kb的模块,并且只使用了文件中的一个常量,会怎么样?python加载一次模块并将其保存在内存中,直到您使用reload它。


    如果您在ipython shell中运行,那么存在一些魔法命令。

    IPython文档包含这个称为自动加载扩展的功能。

    最初,我从JonathanMarch关于这个主题的博客文章中找到了这个解决方案(见链接中的第3点)。

    基本上,您需要做的就是以下操作,您所做的更改会在保存后自动反映出来:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    In [1]: %load_ext autoreload

    In [2]: %autoreload 2

    In [3]: Import MODULE

    In [4]: my_class = Module.class()
            my_class.printham()
    Out[4]: ham

    In [5]: #make changes to printham and save
    In [6]: my_class.printham()
    Out[6]: hamlet

    在从模块中导入所有对象时,我使用了以下方法以确保Web2py使用了我的当前代码:

    1
    2
    3
    4
    5
    6
    import buttons
    import table
    reload(buttons)
    reload(table)
    from buttons import *
    from table import *


    我不太确定这就是你的意思,所以别犹豫纠正我。您在程序中导入了一个模块,我们称之为mymodule.py,但当您更改其内容时,您看不到区别吗?

    python不会在mymodule.py中查找每次使用时的更改,它将第一次加载它,将其编译为字节码并在内部保存它。它通常还保存编译的字节码(mymodule.pyc)。下次启动程序时,它将检查mymodule.py是否比mymodule.pyc更新,并在必要时重新编译。

    如果需要,可以显式重新加载模块:

    1
    2
    3
    4
    5
    6
    import mymodule

    [... some code ...]

    if userAskedForRefresh:
        reload(mymodule)

    当然,它比这更复杂,并且您可能会产生副作用,这取决于您对其他模块的程序所做的操作,例如,如果变量依赖于MyModule中定义的类。

    或者,可以使用execfile函数(或exec()eval()compile())


    对于不同版本的python,情况会有所不同。下面是Python3.4或更高版本的示例:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    hello import hello_world
    #Calls hello_world function
    hello_world()
    HI !!
    #Now changes are done and reload option is needed
    import importlib
    importlib.reload(hello)
    hello_world()
    How are you?

    对于早期的python版本,如2.x,使用上面所述的内置重载函数。更好的是使用ipython3,因为它提供了自动加载功能。


    我在为Arcgis10.2创建地理处理脚本时遇到了同样的问题。我有一个python工具箱脚本,一个工具脚本,然后是一个公共脚本。我在工具中有一个dev/test/prod的参数,可以控制运行的代码版本。dev将运行dev文件夹中的代码,test from test文件夹和prod from prod文件夹中的prod。从ArcCatalog运行该工具时,对公共dev脚本的更改将不会运行。关闭arcCatalog没有什么不同。即使我选择了dev或test,它也总是从prod文件夹运行。

    向工具脚本添加reload(mycommonmodule)解决了这个问题。