Upgrading to OpenDSSDirect.py v0.9+#
If you are using older OpenDSSDirect.py versions, some specifics changed in v0.9 are important to note. For general changes of the DSS engine, please see the changelog at dss-extensions/dss_capi
Basic usage of ODD.py can continue as in previous versions, and should mostly keep working out-of-the-box if you do not intend to use multiple DSS instances. There are also a couple of deprecation warnings introduced to signal some changes to the users.
Instead of using
import opendssdirect as odd
, we now recommendfrom opendssdirect import dss as odd
. This will import a class instance, which exposes more features and is safer. For example, the main class (OpenDSSDirect
) exposes theOpenDSSDirect.Text.Commands
as the call operator – you can useodd('redirect some_script.dss')
, even with multi-line strings.The classes also handle a common mistake of new users, which is using OpenDSSDirect.py as DSS-Python or the COM API, accidentally replacing the functions/methods with the intended values instead. That is, something like
from opendssdirect import dss as odd; odd.Text.Command = 'clear'
now results in an error.The old
Iterator
class is deprecated since all iterable classes should now support the native iterator protocol in Python. That is[load.kW() for load in odd.Loads]
now works. The general behavior from OpenDSS still applies (a single object of a certain type must be active, etc.).opendssdirect.run_command
is also deprecated due to the lack of direct error handling. We noticed this was resulting in error being ignored by many users, especially new users.Multiple DSS engines are now supported, including multi-threading in Python. This means that some old usage patterns are not recommended anymore, since the code moved from plain modules to classes in order to allow this kind of feature.
from opendssdirect import dss as odd_default
# When using multiple contexts, it's better avoid changing the
# working directory of the process
odd_default.Basic.AllowChangeDir(False)
odd1 = odd_default.NewContext()
odd2 = odd_default.NewContext()
odd1('new circuit.circuit1')
odd2('new circuit.circuit2')
assert odd1.Circuit.Name() == 'circuit1'
assert odd2.Circuit.Name() == 'circuit2'
The package now has the option of returning NumPy arrays (like DSS-Python) instead of plain lists. As of v0.9, this is not enabled by default, but it could be in future versions (feedback is welcome). To enable it globally, you can set the environment variable
OPENDSSDIRECT_PY_USE_NUMPY=1
. To enable it on a per-instance base, you can passprefer_lists=False
to the constructor. For example, from one of the tests:
from opendssdirect.OpenDSSDirect import OpenDSSDirect
from numpy import ndarray
# NOTE: this constructors ALWAYS binds to the default DSS engine.
odd_np = OpenDSSDirect(prefer_lists=False)
# Use it normally
odd_np(f"Redirect '{PATH_TO_DSS}'")
assert isinstance(odd_np.Circuit.AllBusMagPu(), ndarray)
odd_lst = OpenDSSDirect(prefer_lists=True)
# Same global instance, we can just reuse the result
assert isinstance(odd_lst.Circuit.AllBusMagPu(), list)
Due to changes in the AltDSS/DSS C-API engine, the capitalization of the DSS properties was changed. OpenDSS is case insensitive, but a lot of third-party code assumes a certain capitalization. This is not recommended since OpenDSS already changed the capitalization in the past. Code that relied on the capitalization before should stop working, but we added a way to toggle the capitalization style through
Settings.SetPropertyNameStyle
, as in the snippet below. We’d recommend using this but updating any related code to not depend on the capitalization at all. Note that there is alsoDSSPropertyNameStyle.Lowercase
which may simplify some comparisons.
from opendssdirect import dss as odd, enums as dss_enums
odd.Settings.SetPropertyNameStyle(dss_enums.DSSPropertyNameStyle.Legacy)
Architecture of version 0.9#
Previous versions of OpenDSSDirect.py only exposed the default OpenDSS engine instance, as that was the how the original OpenDSS worked. With just a single instance, modules used to fit nicely to map the interfaces:
To allow multiple instances and other desirable features like pythonic iteration, indexing, len()
, etc., a new OpenDSSDirect class
was introduced, and the original modules were replaced with instances of dedicated classes:
Finally, to provide better backwards compatibility, in case users imported separate modules directly, the methods bound to the default DSS engine instance/context are exposed in the original module organization.
In the end, importing the default instance is enough to provide the new features:
from opendssdirect import dss
In the long term, the modules could be removed if the community does indeed migrate to the import above. Typically, replacing import opendssdirect as dss
with from opendssdirect import dss
is enough.
The design mirrors the basics of what was done in DSS-Python 0.12 (July 2022) when support for DSSContexts (multiple engines) was introduced, with the caveat that DSS-Python already used a class-based approach. After a few releases, the design seems fit and stable to port over to ODD.py. Besides the extras, especially opendssdirect.utils
, ODD.py is effectively equal to DSS-Python using a different convention, that is, instead of using Python properties like DSS-Python (done to achieve drop-in compatibility with the official COM implementation), OpenDSSDirect.py uses function calls for setters and getters.
For backwards compatibility, and to respect users expectations, OpenDSSDirect.py doesn’t allow/recommend using the constructor of the main interface class directly. Instead, NewContext
must be used.
Using OpenDSSDirect.py with DSS-Python and AltDSS-Python#
Two new functions were introduced to make it easier to map from one module to the other:
This is especially useful now that altdss
exposes most of the classic API in a more pythonic approach, batches and more.
Note
See also DSS-Python and AltDSS-Python.
A multi-threading example#
An example of how to use multiple DSS instances and multi-threading, directly in Python, is available at Multiple DSS engines and multithreading. This would be recommended for most uses instead of the internal/classic Parallel interface.