When writing Python code to be used in Excel, there’s no need to shut down Excel and restart it every time you make a change to your code.
Instead, you can simply tell PyXLL to reload your Python code so you can test it out immediately.
When reloading, the default behaviour is for PyXLL to only reload the Python modules listed in
the modules
list on your pyxll.cfg config file. Optionally, PyXLL can also reload all the modules
that those modules depend on - this is called deep reloading. Deep reloading
can take a bit longer than just reloading the modules listed in the config, but can be helpful when
working on larger projects.
There are different options that affect how and when your Python code is reloaded, which are explained in this document. The different configuration options are also documented in the Configuring PyXLL section of the documentation.
Before you can reload your Python modules with PyXLL, you need to make sure you have developer_mode
enabled in your pyxll.cfg file.
[PYXLL]
developer_mode = 1
This setting enables reloading and adds the “Reload PyXLL” menu item to Excel. It is enabled by default.
After working on some changes to your code you can tell PyXLL to reload your modules by selecting “Reload PyXLL” from the PyXLL menu in the Add-Ins tab.
You can also configure the Excel ribbon to have a “Reload” button. This is done for you in the example ribbon.xml file.
A simple ribbon file with just the “Reload” button would look like this
<customUI xmlns="http://schemas.microsoft.com/office/2006/01/customui">
<ribbon>
<tabs>
<tab id="PyXLL" label="PyXLL">
<group id="Tools" label="Tools">
<button id="Reload"
size="large"
label="Reload PyXLL"
onAction="pyxll.reload" />
</group>
</tab>
</ribbon>
</customUI>
Note the “onAction” attribute is set to “pyxll.reload”. This binds that ribbon button to PyXLL’s reload function.
You can read more about configuring the ribbon here.
Rather than have to reload manually every time you make a change to your code, PyXLL can watch and reload automatically as soon as any of your files are saved.
To enable automatic reloading, set auto_reload = 1
in the [PYXLL]
section of your config file.
[PYXLL]
auto_reload = 1
When automatic reloading is enabled, changes to the following files will cause PyXLL to reload:
Automatic reloading works with deep reloading. If deep reloading is enabled, then any change to a Python module that be reloaded will cause PyXLL to trigger a reload. If deep reloading is not enabled, then only the Python modules listed in the PyXLL config will trigger a reload.
Warning
Automatic reloading is only available from PyXLL 4.3 onwards.
It is possible to reload PyXLL programmatically via the Python function reload
or by calling the
Excel macro pyxll_reload.
Calling either the Python function or the Excel macro will cause PyXLL to reload shortly after. The reload does not happen immediately, but after the current function or macro has completed.
The default behaviour when reloading is that only the modules listed in the pyxll.cfg config file are reloaded.
When working on more complex projects it is normal to have Python code organized into packages, and to have PyXLL functions in many different Python modules. Instead of listing all of them in the config file they can be imported from a single module.
For example, you might have a directory structure something like the following
my_excel_addin
├── __init__.py
├── functions.py
└── macros.py
And in my_excel_addin/__init__.py you might import functions and macros.
from . import functions
from . import macros
In your pyxll.cfg file, you would only need to list my_excel_addin.
[PYXLL]
modules =
my_excel_addin
When you reload PyXLL, only my_excel_addin would be reloaded, and so changes to my_excel_addin.functions or my_excel_addin.macros or any other imported modules wouldn’t be discovered.
With deep reloading, PyXLL determines the dependencies between your imported modules and reloads all of the module dependencies, in the correct order.
To enable deep reloading, set deep_reload = 1
in the [PYXLL]
section of your config file.
[PYXLL]
deep_reload = 1
Not all modules can be reloaded. Sometimes because of the way some modules are written, they won’t reload cleanly. Circular dependencies between modules is a common reason for packages to not reload cleanly, and Python cannot reload C extension modules.
If you are having trouble with a particular package or module not reloading cleanly, you can exclude it
from being reloaded during the deep reload. To do so, list the modules you want excluded in the
deep_reload_exclude
list in your PyXLL config file.
As deep reloading can take longer than normal reloading, you can limit what modules and packages are
included by setting deep_reload_include
in your PyXLL config file. In the example above, because
everything we’re interested in is contained in the my_excel_addin package, adding my_excel_addin
to the deep_reload_include
list would limit reloading to modules in that package.
Warning
Starting with PyXLL 4.3 onwards, packages in the site-packages folder are no longer included when deep reloading.
To include modules in site-packages, set deep_reload_include_site_packages = 1
in the
[PYXLL]
section of your config file.
As well as reloading, it is also possible to tell PyXLL to re-create its bindings between the imported Python code and Excel. This is referred to as rebinding.
Rebinding can be useful, for example, when importing modules dynamically and updating the Excel functions after the import is complete, without reloading.
By default rebinding occurs automatically whenever a new xl_func
, xl_macro
or xl_menu
decorator is called.
Automatic rebinding can be disabled by setting the following in your pyxll.cfg file:
[PYXLL]
auto_rebind = 0
If automatic rebinding has been disabled you can still tell PyXLL to rebind by calling the rebind
function.
For example:
from pyxll import xl_macro, rebind
@xl_macro
def import_new_functions():
"""Import a new module and then call 'rebind' to tell PyXLL to update"""
module = __import__("...")
# Now the module has been imported and declared new UDFs using @xl_func
# tell PyXLL to update it's Excel bindings.
rebind()
PyXLL also declares an Excel macro pyxll_rebind
that you can call from VBA to do the same as the
Python rebind
function.