Skip to content

Server32¤

Base class for loading a 32-bit library in 32-bit Python.

Server32 is used in combination with Client64 to communicate with a 32-bit library from 64-bit Python.

Server32 ¤

Server32(path, libtype, host, port, **kwargs)

Bases: HTTPServer

Base class for loading a 32-bit library in 32-bit Python.

All modules that are to be run on the 32-bit server must contain a class that inherits this class. The module may import most of the standard python modules (graphic-related modules, e.g., tkinter, are not available).

Parameters:

Name Type Description Default
path PathLike

The path to the 32-bit library (see LoadLibrary)

required
libtype LibType

The library type (see LoadLibrary).

Attention

Since Java byte code is executed on the JVM it does not make sense to use Server32 for a Java .jar or .class file. Use LoadLibrary to load a Java library.

required
host str

The IP address (or hostname) to use for the server.

required
port int

The port to open for the server.

required
kwargs Any

All keyword arguments are passed to LoadLibrary.

{}
Source code in src/msl/loadlib/server32.py
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
def __init__(self, path: PathLike, libtype: LibType, host: str, port: int, **kwargs: Any) -> None:
    """Base class for loading a 32-bit library in 32-bit Python.

    All modules that are to be run on the 32-bit server must contain a class
    that inherits this class. The module may import most of the
    [standard](https://docs.python.org/3/py-modindex.html){:target="_blank"}
    python modules (graphic-related modules, e.g., [tkinter][]{:target="_blank"},
    are not available).

    Args:
        path: The path to the 32-bit library (see [LoadLibrary][msl.loadlib.load_library.LoadLibrary])
        libtype: The library type (see [LoadLibrary][msl.loadlib.load_library.LoadLibrary]).

            !!! attention
                Since Java byte code is executed on the
                [JVM](https://en.wikipedia.org/wiki/Java_virtual_machine){:target="_blank"}
                it does not make sense to use [Server32][] for a Java `.jar` or `.class` file.
                Use [LoadLibrary][msl.loadlib.load_library.LoadLibrary] to load a Java library.

        host: The IP address (or hostname) to use for the server.
        port: The port to open for the server.
        kwargs: All keyword arguments are passed to [LoadLibrary][msl.loadlib.load_library.LoadLibrary].
    """
    self._library: LoadLibrary = LoadLibrary(path, libtype=libtype, **kwargs)
    self._app: Application | None = self._library.application
    self._assembly: Any = self._library.assembly
    self._lib: Any = self._library.lib
    self._path: str = self._library.path
    super().__init__((host, int(port)), _RequestHandler, bind_and_activate=False)

application property ¤

application

Application | None — Reference to the ActiveX application window.

If the loaded library is not an ActiveX library, returns None.

When an ActiveX library is loaded, the window is not shown (to show it call Application.show) and the message loop is not running (to run it call Application.run).

Added in version 1.0

assembly property ¤

assembly

Returns a reference to the .NET Runtime Assembly object.

If the loaded library is not a .NET library, returns None.

Tip

The JetBrains dotPeek program can be used to decompile a .NET Assembly.

lib property ¤

lib

Returns the reference to the library object.

For example, if libtype is

path property ¤

path

str — The path to the library file.

examples_dir staticmethod ¤

examples_dir()

Path — The directory where the example libraries are located.

Added in version 0.9

Changed in version 1.0

The return type changed from str to Path.

Source code in src/msl/loadlib/server32.py
226
227
228
229
230
231
232
233
234
235
@staticmethod
def examples_dir() -> Path:
    """[Path][pathlib.Path] — The directory where the [example][direct] libraries are located.

    !!! note "Added in version 0.9"
    !!! note "Changed in version 1.0"
        The return type changed from [str][]{:target="_blank"} to [Path][pathlib.Path]{:target="_blank"}.
    """
    path = sys.executable if Server32.is_interpreter() else __file__
    return Path(path).parent.parent / "examples" / "loadlib"

interactive_console staticmethod ¤

interactive_console()

Start an interactive console.

This method starts an interactive console, in a new terminal, with the Python interpreter on the 32-bit server.

Tip

You can start the console from a terminal by running

python -c "from msl.loadlib import Server32; Server32.interactive_console()"

Source code in src/msl/loadlib/server32.py
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
@staticmethod
def interactive_console() -> None:
    """Start an [interactive console]{:target="_blank"}.

    This method starts an [interactive console]{:target="_blank"}, in a new terminal,
    with the Python interpreter on the 32-bit server.

    !!! tip
        You can start the console from a terminal by running
        ```console
        python -c "from msl.loadlib import Server32; Server32.interactive_console()"
        ```

    [interactive console]: https://docs.python.org/3/tutorial/interpreter.html#interactive-mode
    """
    exe = Path(__file__).parent / server_filename
    if IS_WINDOWS:
        cmd = f'start "msl.loadlib.Server32 || interactive console" "{exe}" --interactive'
    else:
        cmd = f"gnome-terminal --command='{exe} --interactive'"
    _ = os.system(cmd)  # noqa: S605

is_interpreter staticmethod ¤

is_interpreter()

Check if code is running on the 32-bit server.

If the same module is executed by both Client64 and Server32 then there may be sections of the code that should only be executed by the correct bitness of the Python interpreter.

Example:

import sys
from msl.loadlib import Client64, Server32

if Server32.is_interpreter():
    # Only executed on the 32-bit server
    assert sys.maxsize < 2**32

Returns:

Type Description
bool

Whether the module is running on the 32-bit server.

Added in version 0.9

Source code in src/msl/loadlib/server32.py
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
@staticmethod
def is_interpreter() -> bool:
    """Check if code is running on the 32-bit server.

    If the same module is executed by both [Client64][] and [Server32][]
    then there may be sections of the code that should only be executed
    by the correct bitness of the Python interpreter.

    **Example:**

    ```python
    import sys
    from msl.loadlib import Client64, Server32

    if Server32.is_interpreter():
        # Only executed on the 32-bit server
        assert sys.maxsize < 2**32
    ```

    Returns:
        Whether the module is running on the 32-bit server.

    !!! note "Added in version 0.9"
    """
    return sys.executable.endswith(server_filename)

remove_site_packages_64bit staticmethod ¤

remove_site_packages_64bit()

Remove the site-packages directory from the 64-bit process.

By default, the site-packages directory of the 64-bit process is included in sys.path of the 32-bit process. Having the 64-bit site-packages directory available can sometimes cause issues. For example, comtypes tries to import numpy so if numpy is installed in the 64-bit process then comtypes will import the 64-bit version of numpy in the 32-bit process. Depending on the version of Python and/or numpy this can cause the 32-bit server to crash.

Example:

import sys
from msl.loadlib import Server32

class FileSystem(Server32):

    def __init__(self, host, port):

        # Remove the site-packages directory that was passed from 64-bit Python
        path = Server32.remove_site_packages_64bit()

        # Load the COM library (this is when `comtypes` gets imported)
        super().__init__("Scripting.FileSystemObject", "com", host, port)

        # Optional: add the site-packages directory back into sys.path
        sys.path.append(path)

Returns:

Type Description
str

The path to the site-packages directory that was removed. Can be an empty string if the directory was not found in sys.path.

Added in version 0.9

Source code in src/msl/loadlib/server32.py
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
@staticmethod
def remove_site_packages_64bit() -> str:
    """Remove the _site-packages_ directory from the 64-bit process.

    By default, the _site-packages_ directory of the 64-bit process is
    included in [sys.path][] of the 32-bit process. Having the
    64-bit _site-packages_ directory available can sometimes cause issues.
    For example, `comtypes` tries to import `numpy` so if `numpy` is
    installed in the 64-bit process then `comtypes` will import the
    64-bit version of `numpy` in the 32-bit process. Depending on the
    version of Python and/or `numpy` this can cause the 32-bit server
    to crash.

    **Example:**

    ```python
    import sys
    from msl.loadlib import Server32

    class FileSystem(Server32):

        def __init__(self, host, port):

            # Remove the site-packages directory that was passed from 64-bit Python
            path = Server32.remove_site_packages_64bit()

            # Load the COM library (this is when `comtypes` gets imported)
            super().__init__("Scripting.FileSystemObject", "com", host, port)

            # Optional: add the site-packages directory back into sys.path
            sys.path.append(path)
    ```

    Returns:
        The path to the _site-packages_ directory that was removed.
            Can be an empty string if the directory was not found in [sys.path][].

    !!! note "Added in version 0.9"
    """
    for index, path in enumerate(sys.path):
        if path.endswith("site-packages"):
            return sys.path.pop(index)
    return ""

shutdown_handler ¤

shutdown_handler()

Called just before the server shuts down.

Override this method to do any necessary cleanup, such as stopping threads or closing file handles, before the server shuts down.

Added in version 0.6

Source code in src/msl/loadlib/server32.py
237
238
239
240
241
242
243
244
def shutdown_handler(self) -> None:
    """Called just before the server shuts down.

    Override this method to do any necessary cleanup, such as stopping
    threads or closing file handles, before the server shuts down.

    !!! note "Added in version 0.6"
    """

version staticmethod ¤

version()

str — The version of Python that the 32-bit server is running on.

Tip

You can view the version from a terminal by running

python -c "from msl.loadlib import Server32; print(Server32.version())"

Source code in src/msl/loadlib/server32.py
121
122
123
124
125
126
127
128
129
130
131
132
@staticmethod
def version() -> str:
    """[str][] &mdash; The version of Python that the 32-bit server is running on.

    !!! tip
        You can view the version from a terminal by running
        ```console
        python -c "from msl.loadlib import Server32; print(Server32.version())"
        ```
    """
    exe = Path(__file__).parent / server_filename
    return subprocess.check_output([exe, "--version"]).decode().strip()  # noqa: S603