Python

How to install python3 on pfSense

First, login to your pfSense as root using ssh.

Then use

pkg search python

to show which python versions are available. Output on pfSense 2.6.0:

frr7-pythontools-7.5.1_3       Provide configuration reload functionality for FRR
py38-gitpython-3.1.24          Python Git Library
python38-3.8.12_1              Interpreted object-oriented programming language

Now run e.g.

pkg install python38-3.8.12_1

On my pfSense, python3.8 was already installed.

Remember that in order to run python, you need to explicitly run python3.8, just running python or python3 won’t work!

Posted by Uli Köhler in Networking, Python

How to fix PyVISA ValueError: Please install PyUSB to use this resource type

Problem:

When trying to run a Python script using PyVISA with a USB instrument, you see the following error message:

ValueError: Please install PyUSB to use this resource type.
No module named 'usb'

Solution:

On Linux distributions such as Ubuntu, you can fix this using

sudo apt-get -y install python3-usb

This will install the Python3 usb package and the libusb system packages.

Posted by Uli Köhler in Python

How to format axis as dB (decibel) using matplotlib

In our previous post Matplotlib custom SI-prefix unit tick formatter we showed how to format a matplotlib Y axis with a custom unit with SI prefixes.

Similarly, we can use UliEngineering.Math.Decibel in order to format plots (most notably plots with a logarithmic Y axis) as decibels:

from UliEngineering.Math.Decibel import *
import matplotlib.ticker as mtick

def decibel_formatter(v0=1.0, unit='dB'):
    def format_value(value, pos=None):
        dB = value_to_dB(value, v0=v0)
        return f'{dB:.0f} {unit}'
    return format_value

# Usage example:
plt.gca().set_yscale("log") # Optional

plt.gca().yaxis.set_major_formatter(mtick.FuncFormatter(decibel_formatter()))

 

Posted by Uli Köhler in Python

How to fix erpc ValueError: The generated shim code version … is different to the rest of eRPC code

Problem:

When trying to import your erpc project generated Python code using e.g.

from erpc_myproject import *

You see the following error message:

Traceback (most recent call last)
Cell In [1], line 1
----> 1 from erpc_myproject import *

File ./erpc_myproject/__init__.py:13
     11     version = "unknown"
     12 if version != "1.9.1":
---> 13     raise ValueError("The generated shim code version (1.9.1) is different to the rest of eRPC code (%s). \
     14 Install newer version by running \"python setup.py install\" in folder erpc/erpc_python/." % repr(version))
     16 from . import common
     17 from . import client

ValueError: The generated shim code version (1.9.1) is different to the rest of eRPC code ('unknown'). Install newer version by running "python setup.py install" in folder erpc/erpc_python/.

Solution:

Either you have not installed the erpc Python library (if the error message lists ... different to the rest of eRPC code ('unknown')) or you have installed the wrong version (e.g. ... (1.9.1) is different to the rest of eRPC code ('1.10.0')).

If you have not installed erpc at all, simply use

pip install erpc

and retry running your script.

If you have installed the wrong version, you have two options:

Option 1 (preferred): Re-generate the code

Just use the original command (some erpcgen call) you’ve used to re-generate the code using the currently installed version.

Option 2: Install the correct version

For this, you need to determine what the correct version is. Let’s consider the following error message:

ValueError: The generated shim code version (1.9.1) is different to the rest of eRPC code ('1.10.0'). Install newer version by running "python setup.py install" in folder erpc/erpc_python/.

From this message, we can read that the shim code version is 1.9.1 whereas you have 1.10.0 installed. Therefore, in order to make it work, we need to install erpc version 1.9.1.

Install it using

pip install -U erpc==1.9.1

and then retry your command. If you are using jupyter notebooks or similar, you need to restart your kernel to load the new library!

Posted by Uli Köhler in Embedded, Python

How to iterate all IP addresses in network using Python

The following code will iterate over all IP addresses in the given network, i.e. 192.168.1.0 ... 192.168.1.254:

import ipaddress

network = ipaddress.ip_network('192.168.1.0/24')

for ip in network:
    print(ip)

The following variant will iterate over all IP addresses in this network except the broadcast IP address 192.168.1.255 and the network IP address 192.168.1.0:

import ipaddress

network = ipaddress.ip_network('192.168.1.0/24')

for ip in network:
    # Ignore e.g. 192.168.1.0 and 192.168.1.255
    if ip == network.broadcast_address or ip == network.network_address:
        continue
    print(ip)

 

Posted by Uli Köhler in Python

How to fix pip fatal error: portaudio.h: No such file or directory

Problem:

While trying to install a package using pip, you see the following error message:

x86_64-linux-gnu-gcc -Wno-unused-result -Wsign-compare -DNDEBUG -g -fwrapv -O2 -Wall -g -fstack-protector-strong -Wformat -Werror=format-security -g -fwrapv -O2 -fPIC -I/usr/local/include -I/usr/include -I/usr/include/python3.10 -c src/pyaudio/device_api.c -o build/temp.linux-x86_64-3.10/src/pyaudio/device_api.o
src/pyaudio/device_api.c:9:10: fatal error: portaudio.h: No such file or directory
    9 | #include "portaudio.h"
      |          ^~~~~~~~~~~~~
compilation terminated.
error: command '/usr/bin/x86_64-linux-gnu-gcc' failed with exit code 1
[end of output]

Solution:

On Ubuntu, you need to install the portaudio19-dev package:

sudo apt -y install portaudio19-dev

 

Posted by Uli Köhler in Python

How to compute voltage divider output voltage using Python

You can use the UliEngineering library to compute the output voltage of a voltage divider by its top resistor, bottom resistor and its input voltage:

from UliEngineering.Electronics.VoltageDivider import *

# Voltage divider with 1MΩ and 150kΩ resistors & 24V input voltage
print(voltage_divider_voltage("1MΩ", "150kΩ", "24V")) # Print 3.1304347826086953

You can also directly format this voltage using auto_format():

from UliEngineering.EngineerIO import auto_format

# Print formatted as volts
print(auto_format(voltage_divider_voltage, "1MΩ", "150kΩ", "24V")) # Prints "3.13 V"
Posted by Uli Köhler in Electronics, Python

How to compute MRI Larmor frequency for a given magnetic field using Python

You can use the UliEngineering library to compute the larmor frequency for a given magnetic field in Tesla using Python.

from UliEngineering.Physics.MagneticResonance import *

# Default is to compute the Larmor frequency for hydrogen (H1 nucleus)
# Print frequency [Hz] for a 1.0 T magnetic field
print(larmor_frequency(1.0)) # Prints 42576384.74

# Compute for another nucleus like He3
print(larmor_frequency(1.0, nucleus_larmor_frequency=NucleusLarmorFrequency.He3)) # Prints 32434099.42

You can also directly format this frequency using auto_format():

# Format frequency
from UliEngineering.EngineerIO import auto_format
print(auto_format(larmor_frequency, 1.0)) # Prints "42.6 MHz"
Posted by Uli Köhler in Medical devices, Physics, Python

How to fix Python tox ImportError: cannot import name ‘cmdline’ from ‘tox’

Problem:

When trying to run your unit tests using tox you see the following error message:

Traceback (most recent call last):
  File "/home/uli/.local/bin/tox", line 5, in <module>
    from tox import cmdline
ImportError: cannot import name 'cmdline' from 'tox' (/usr/local/lib/python3.10/dist-packages/tox/__init__.py)

Solution:

You’re using an older version of tox as an executable. To find out which executable you’re using, check this line of the error message:

File "/home/uli/.local/bin/tox", line 5, in <module>

In our case, the executable is

/home/uli/.local/bin/tox

Delete that file!

After that, tox should work fine. If not, update tox using

pip install -U tox

 

Posted by Uli Köhler in Python

How to fix AttributeError: module ‘scipy’ has no attribute ‘constants’

Problem:

While trying to run your Python project, you see an error message like

AttributeError: module 'scipy' has no attribute 'constants'

even though have have already imported scipy:

import scipy

Solution:

You need to explicitly import scipy.constants

import scipy.constants

I generally recommend to import both scipy and scipy.constants in case you use scipy itself elsewhere in your code:

import scipy
import scipy.constants

 

 

Posted by Uli Köhler in Python

How to parse filename extension from URL using Python

If you have an URL like

https://logodix.com/logo/1667872.jpg?param=value

and you want to find just the filename extension (.jpg for this example), use the following code:

from urllib.parse import urlsplit
import os.path

url = "https://logodix.com/logo/1667872.jpg?param=value"

path = urlsplit(url).path
extension = os.path.splitext(path)[-1] # e.g. ".jpg"

 

Posted by Uli Köhler in Python

How to fix Python 3 AttributeError: ‘function’ object has no attribute ‘urlsplit’

Problem:

When trying to urlsplit an URL in Python 3:

from urllib.parse import urlparse

path = urlparse.urlsplit(remote_image_url).path

you see the following error message:

AttributeError                            Traceback (most recent call last)
Input In [30], in <cell line: 3>()
      1 from urllib.parse import urlparse
----> 3 path = urlparse.urlsplit(remote_image_url).path
      4 filename = posixpath.basename(path)

AttributeError: 'function' object has no attribute 'urlsplit'

Solution:

The equivalent of urlparse.urlsplit() in Python 3 is urllib.parse.urlsplit().

Therefore, a working code example is

from urllib.parse import urlsplit

path = urlsplit(remote_image_url).path

 

Posted by Uli Köhler in Python

How to fix Python 3 ModuleNotFoundError: No module named ‘urlparse’

Problem:

While trying to import urlparse in Python 3 using

import urlparse

you see the following error message:

---------------------------------------------------------------------------
ModuleNotFoundError                       Traceback (most recent call last)
Input In [29], in <cell line: 1>()
----> 1 import urlparse

ModuleNotFoundError: No module named 'urlparse'

Solution:

In Python 3, urlparse has been renamed to urllib.urlparse. In order to import it, use this line instead:

from urllib.parse import urlparse

 

Posted by Uli Köhler in Python

How to auto-restart bottle server when Python file changes using nodemon

Assuming you have a Python script server.py that you want to auto-reload every time the file changes, use the following script using nodemon:

nodemon -w . --exec python server.py

The -w . tells  nodemon files to watch for changes of all files in the current directory (.)

I generally recommend creating a script start.sh to automatically run this command:

#!/bin/sh
nodemon -w . --exec python server.py

and then make it executable using

chmod a+x start.sh

Now you can run it using

./start.sh

 

Posted by Uli Köhler in Python

How to return JSON array using bottle – minimal example

Returning a JSON array in bottle involves setting the response content type to application/json and then manually dumping the array using json.dumps():

#!/usr/bin/env python3
from bottle import route, run, response
import json

@route('/')
def json_array():
    response.content_type = 'application/json'
    return json.dumps(["a", "b", "c"])

run(host='localhost', port=9000)

 

Posted by Uli Köhler in Python

How to auto-restart bottle server when Python file changes using entr

Note: I do not recommend using entr any more since for me it doesn’t work reliably. I recommend using nodemon instead, see How to auto-restart bottle server when Python file changes using nodemon

Assuming you have a Python script server.py that you want to auto-reload every time the file changes, use the following script using entr:

ls *.py | entr python server.py

The ls *.py tells entr which files to watch for changes.

Posted by Uli Köhler in Python

Bottle HTTP server with dedicated server class – minimal example

This script uses a dedicated class MyServer to encapsulate the bottle server appropriately. Compared to our previous post Python bottle minimal example it provides better encapsulation of the server at the cost of slightly more lines of code.

#!/usr/bin/env python3
from bottle import Bottle, run

class MyServer(object):
    def __init__(self):
        self.app = Bottle()
        self.init_routes()
        
    def init_routes(self):
        """Initialize all routes"""
        @self.app.route('/hello')
        def hello():
            return "Hello World!"

    def run(self):
        run(self.app, host='0.0.0.0', port=8080)
        
# Example usage
if __name__ == "__main__":
    server = MyServer()
    server.run()

How to use

Run the server

python bottle-server.py

and open

http://localhost:8080/hello

Now you should see the Hello World! message.

Posted by Uli Köhler in Python

Inventree Python API: How to list all stock locations

See our previous post Inventree Python API: Minimal API connect example using YAML config for our method of creating the api object using a YAML config file!

from inventree.stock import StockLocation

all_stock_locations = StockLocation.list(api)

# Dict of part categories by name
# (e.g. 'OpAmps')
stock_locations_by_name = {
    category["name"]: category
    for category in all_stock_locations
}
# Dict of part categories by public key (e.g. 7)
part_locations_by_pk = {
    category.pk: category
    for category in all_stock_locations
}
# Dict of part categories by hierarchical path
# (e.g. 'Office/Spart parts box')
stock_locations_by_pathstring = {
    category.pathstring: category
    for category in all_stock_locations
}

 

Posted by Uli Köhler in InvenTree, Python

Inventree Python API: How to create a new part

See our previous post Inventree Python API: Minimal API connect example using YAML config for our method of creating the api object using a YAML config file!

The following code finds a part category called ICs and creates a new part in that category.

First, we need to fetch the part categories, this is from our previous post Inventree Python API: Minimal API connect example using YAML config:

from inventree.part import PartCategory

all_categories = PartCategory.list(api)

# Dict of part categories by name
# (e.g. 'OpAmps')
part_categories_by_name = {
    category["name"]: category
    for category in all_categories
}
# Dict of part categories by public key (e.g. 7)
part_categories_by_pk = {
    category.pk: category
    for category in all_categories
}
# Dict of part categories by hierarchical path
# (e.g. 'Electronics-Components/ICs/OpAmps')
part_categories_by_pathstring = {
    category.pathstring: category
    for category in all_categories
}

Now let’s select the correct category:

ics = part_categories_by_name['ICs']

Now it’s finally time to create the part:

from inventree.part import Part

new_part = Part.create(api, {
    'name': 'L78L33ABD',
    'description': '100mA 3.3V fixed LDO regulator, SOIC-8',
    'category': ics.pk
})

You can read the primary key (pk) for the newly generated part using

new_part.pk
Posted by Uli Köhler in InvenTree, Python