Python

How to fix Python pyarrow pip install error: Could NOT find Arrow (missing: Arrow_DIR)

Problem:

When trying to install pyarrow such as using

pip install pyarrow

you see an error log like

      -- Found Python3Alt: /home/uli/.pypy3-virtualenv/bin/pypy3
      CMake Warning (dev) at /usr/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:273 (message):
        The package name passed to `find_package_handle_standard_args` (PkgConfig)
        does not match the name of the calling package (Arrow).  This can lead to
        problems in calling code that expects `find_package` result variables
        (e.g., `_FOUND`) to follow a certain pattern.
      Call Stack (most recent call first):
        /usr/share/cmake-3.18/Modules/FindPkgConfig.cmake:59 (find_package_handle_standard_args)
        cmake_modules/FindArrow.cmake:39 (include)
        cmake_modules/FindArrowPython.cmake:46 (find_package)
        CMakeLists.txt:229 (find_package)
      This warning is for project developers.  Use -Wno-dev to suppress it.
      
      -- Found PkgConfig: /usr/bin/pkg-config (found version "0.29.2")
      -- Could NOT find Arrow (missing: Arrow_DIR)
      -- Checking for module 'arrow'
      --   No package 'arrow' found
      CMake Error at /usr/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:165 (message):
        Could NOT find Arrow (missing: ARROW_INCLUDE_DIR ARROW_LIB_DIR
        ARROW_FULL_SO_VERSION ARROW_SO_VERSION)
      Call Stack (most recent call first):
        /usr/share/cmake-3.18/Modules/FindPackageHandleStandardArgs.cmake:458 (_FPHSA_FAILURE_MESSAGE)
        cmake_modules/FindArrow.cmake:450 (find_package_handle_standard_args)
        cmake_modules/FindArrowPython.cmake:46 (find_package)
        CMakeLists.txt:229 (find_package)
      
      
      -- Configuring incomplete, errors occurred!
      See also "/tmp/pip-install-409dctif/pyarrow_b70cde6894c3469483f7360493fc2e65/build/temp.linux-x86_64-pypy39/CMakeFiles/CMakeOutput.log".
      error: command '/usr/bin/cmake' failed with exit code 1
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
  ERROR: Failed building wheel for pyarrow
Failed to build pyarrow
ERROR: Could not build wheels for pyarrow, which is required to install pyproject.toml-based projects

Solution:

You need to install the arrow library in order to be able to compile pyarrow from source. On Ubuntu, this can be done using

sudo apt install -y -V ca-certificates lsb-release wget
wget https://apache.jfrog.io/artifactory/arrow/$(lsb_release --id --short | tr 'A-Z' 'a-z')/apache-arrow-apt-source-latest-$(lsb_release --codename --short).deb -O /tmp/apache-arrow.deb
sudo apt -y install /tmp/apache-arrow.deb
sudo apt -y update
sudo apt -y install libarrow-dev libarrow-python-dev

 

Posted by Uli Köhler in Python

How to fix Python Pillow pip install exception: RequiredDependencyException: jpeg

Problem:

When trying to install pillow such as using

pip install Pillow

you see an error log like

      running build_ext
      
      
      The headers or library files could not be found for jpeg,
      a required dependency when compiling Pillow from source.
      
      Please see the install instructions at:
         https://pillow.readthedocs.io/en/latest/installation.html
      
      Traceback (most recent call last):
        File "/tmp/pip-install-_g5fa7ox/pillow_7cb18c0d6bec468e8844184b98c8bf45/setup.py", line 989, in <module>
          setup(
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/__init__.py", line 87, in setup
          return distutils.core.setup(**attrs)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/core.py", line 148, in setup
          return run_commands(dist)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/core.py", line 163, in run_commands
          dist.run_commands()
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/dist.py", line 967, in run_commands
          self.run_command(cmd)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/dist.py", line 1214, in run_command
          super().run_command(command)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/dist.py", line 986, in run_command
          cmd_obj.run()
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/command/install.py", line 68, in run
          return orig.install.run(self)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/command/install.py", line 670, in run
          self.run_command('build')
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/cmd.py", line 313, in run_command
          self.distribution.run_command(command)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/dist.py", line 1214, in run_command
          super().run_command(command)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/dist.py", line 986, in run_command
          cmd_obj.run()
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/command/build.py", line 136, in run
          self.run_command(cmd_name)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/cmd.py", line 313, in run_command
          self.distribution.run_command(command)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/dist.py", line 1214, in run_command
          super().run_command(command)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/dist.py", line 986, in run_command
          cmd_obj.run()
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/command/build_ext.py", line 79, in run
          _build_ext.run(self)
        File "/home/uli/.pypy3-virtualenv/lib/pypy3.9/site-packages/setuptools/_distutils/command/build_ext.py", line 339, in run
          self.build_extensions()
        File "/tmp/pip-install-_g5fa7ox/pillow_7cb18c0d6bec468e8844184b98c8bf45/setup.py", line 804, in build_extensions
          raise RequiredDependencyException(f)
      RequiredDependencyException: jpeg
      
      During handling of the above exception, another exception occurred:
      
      Traceback (most recent call last):
        File "<string>", line 2, in <module>
        File "<pip-setuptools-caller>", line 34, in <module>
        File "/tmp/pip-install-_g5fa7ox/pillow_7cb18c0d6bec468e8844184b98c8bf45/setup.py", line 1009, in <module>
          raise RequiredDependencyException(msg)
      RequiredDependencyException:
      
      The headers or library files could not be found for jpeg,
      a required dependency when compiling Pillow from source.
      
      Please see the install instructions at:
         https://pillow.readthedocs.io/en/latest/installation.html
      
      
      [end of output]
  
  note: This error originates from a subprocess, and is likely not a problem with pip.
error: legacy-install-failure

× Encountered error while trying to install package.
╰─> Pillow

Solution:

Pillow needs a buch of libraries to be installed in order to work properly. Use the following command from the official Pillow website on Ubuntu:

sudo apt-get install cmake libtiff5-dev libjpeg8-dev libopenjp2-7-dev zlib1g-dev libfreetype6-dev liblcms2-dev libwebp-dev tcl8.6-dev tk8.6-dev python3-tk libharfbuzz-dev libfribidi-dev libxcb1-dev

or check out the installation guide for commands for other operating systems.

Posted by Uli Köhler in Python

How to fix Python MongoDB TypeError: Object of type ObjectId is not JSON serializable

Problem:

When trying to export data as JSON that has originally been queried from MongoDB using code like

with open("alle.json", "w") as outfile:
    json.dump(alle, outfile)

you see the following error message:

File /usr/lib/python3.9/json/__init__.py:179, in dump(obj, fp, skipkeys, ensure_ascii, check_circular, allow_nan, cls, indent, separators, default, sort_keys, **kw)
    173     iterable = cls(skipkeys=skipkeys, ensure_ascii=ensure_ascii,
    174         check_circular=check_circular, allow_nan=allow_nan, indent=indent,
    175         separators=separators,
    176         default=default, sort_keys=sort_keys, **kw).iterencode(obj)
    177 # could accelerate with writelines in some versions of Python, at
    178 # a debuggability cost
--> 179 for chunk in iterable:
    180     fp.write(chunk)

File /usr/lib/python3.9/json/encoder.py:429, in _make_iterencode.<locals>._iterencode(o, _current_indent_level)
    427     yield _floatstr(o)
    428 elif isinstance(o, (list, tuple)):
--> 429     yield from _iterencode_list(o, _current_indent_level)
    430 elif isinstance(o, dict):
    431     yield from _iterencode_dict(o, _current_indent_level)

File /usr/lib/python3.9/json/encoder.py:325, in _make_iterencode.<locals>._iterencode_list(lst, _current_indent_level)
    323         else:
    324             chunks = _iterencode(value, _current_indent_level)
--> 325         yield from chunks
    326 if newline_indent is not None:
    327     _current_indent_level -= 1

File /usr/lib/python3.9/json/encoder.py:405, in _make_iterencode.<locals>._iterencode_dict(dct, _current_indent_level)
    403         else:
    404             chunks = _iterencode(value, _current_indent_level)
--> 405         yield from chunks
    406 if newline_indent is not None:
    407     _current_indent_level -= 1

File /usr/lib/python3.9/json/encoder.py:438, in _make_iterencode.<locals>._iterencode(o, _current_indent_level)
    436         raise ValueError("Circular reference detected")
    437     markers[markerid] = o
--> 438 o = _default(o)
    439 yield from _iterencode(o, _current_indent_level)
    440 if markers is not None:

File /usr/lib/python3.9/json/encoder.py:179, in JSONEncoder.default(self, o)
    160 def default(self, o):
    161     """Implement this method in a subclass such that it returns
    162     a serializable object for ``o``, or calls the base implementation
    163     (to raise a ``TypeError``).
   (...)
    177 
    178     """
--> 179     raise TypeError(f'Object of type {o.__class__.__name__} '
    180                     f'is not JSON serializable')

TypeError: Object of type ObjectId is not JSON serializable

Solution:

This error occurs because objects queried from PyMongo always contain _id which is of type ObjectId and the normal JSON library (or drop-in replacements like simplejson do not know how to create JSON representations of Objects of type ObjectId).

In order to fix this, use pymongo‘s json_util instead of json. Note that the bson.json_util package contains dumps but does not contain dump, so use the following snippet to write to a file:

 

import bson.json_util as json_util

with open("alle.json", "w") as outfile:
    outfile.write(json_util.dumps(alle))

 

Posted by Uli Köhler in MongoDB, Python

How to iterate all databases in PyMongo

This short example shows how to iterate all databases or list all database names for a MongoDB in Python using pymongo:

from pymongo import MongoClient

client = MongoClient("mongodb://localhost")

for database in client.list_databases():
    print(database['name'])

s

Posted by Uli Köhler in Python

How to start Jupyter Lab for remote access

This will start Jupyter listening on all network interfaces / bind to all IP addresses in order to make direct browser access possible not only from localhost but any remote host that has network access to the host where you’re running Jupyter:

jupyter lab --ip=0.0.0.0

 

Posted by Uli Köhler in Networking, Python

How to fix Jupyter Lab ImportError: cannot import name ‘soft_unicode’ from ‘markupsafe’

Problem:

When running

jupyter lab

you see the following error message:

Traceback (most recent call last):
  File "/usr/local/bin/jupyter-lab", line 5, in <module>
    from jupyterlab.labapp import main
  File "/usr/local/lib/python3.8/dist-packages/jupyterlab/labapp.py", line 13, in <module>
    from jupyter_server.serverapp import flags
  File "/usr/local/lib/python3.8/dist-packages/jupyter_server/serverapp.py", line 39, in <module>
    from jinja2 import Environment, FileSystemLoader
  File "/usr/lib/python3/dist-packages/jinja2/__init__.py", line 33, in <module>
    from jinja2.environment import Environment, Template
  File "/usr/lib/python3/dist-packages/jinja2/environment.py", line 15, in <module>
    from jinja2 import nodes
  File "/usr/lib/python3/dist-packages/jinja2/nodes.py", line 23, in <module>
    from jinja2.utils import Markup
  File "/usr/lib/python3/dist-packages/jinja2/utils.py", line 656, in <module>
    from markupsafe import Markup, escape, soft_unicode
ImportError: cannot import name 'soft_unicode' from 'markupsafe' (/usr/local/lib/python3.8/dist-packages/markupsafe/__init__.py)

Solution:

You need to install an older version of markupsafe using

sudo pip3 install markupsafe==2.0.1

until other packages have been updated.

Posted by Uli Köhler in Python

Recommended procedure for profiling python scripts

Assuming we want to profile myscript.py, run:

python3 -m cProfile -o myscript.profile myscript.py

In order to view it, I strongly recommend runsnakerun:

runsnake myscript.profile

You can install runsnake on Ubuntu using

sudo apt -y install runsnakerun

 

Posted by Uli Köhler in Python

How to set DLS ContactMe request to OpenStage 40 phones using Python

This snippet sends a ContactMe DLS provisioning request to an OpenStage 40 phone at IP 192.168.178.245 using Python. The phone will then contact 192.168.178.10 on port 18443 using HTTPS. By default (i.e. if the OpenStage 40 is not in Secure Mode, the certificate is not verified – any certificate will do!)

import requests

response = requests.post("http://192.168.178.245:8085/contact_dls.html/ContactDLS", data={
    "ContactMe": True,
    "dls_ip_addr": "192.168.178.10",
    "dls_ip_port": 18443
})
# Response will be <Response [204]> i.e. no content

Note that dls_ip_addr may also be a hostname!

Posted by Uli Köhler in Networking, Python

How to put text into input element in Pyppeteer

In Pyppeteer, if you have an input like this one:

<input id="myInput">

you can fill with text like abc123 by using page.type() like in this snippet:

await page.type('#myInput', 'abc123')

Full example

This example fetches techoverflow.net and puts my search into the search query input on the top right:

#!/usr/bin/env python3
import asyncio
from pyppeteer import launch

async def main():
    browser = await launch()
    page = await browser.newPage()
    await page.goto('https://www.techoverflow.net')
    # Fill text with input
    await page.type('.search-form-input', 'my search')
    # Make screenshot
    await page.screenshot({'path': 'screenshot.png'})
    # Cleanup
    await browser.close()

asyncio.get_event_loop().run_until_complete(main())

 

Posted by Uli Köhler in Pyppeteer, Python

How to disable SSL certificate verification in Pyppeteer

If you see an error message like

pyppeteer.errors.PageError: net::ERR_CERT_AUTHORITY_INVALID at https://10.9.5.12/

in Pyppeteer and you are sure that you just want to skip certificate verification change

browser = await launch()

to

browser = await launch({"ignoreHTTPSErrors": True})

or add "ignoreHTTPSErrors": True to the list of parameters to launch if you already have other parameters there. This will just ignore the net::ERR_CERT_AUTHORITY_INVALID and other, related HTTPS errors.

Posted by Uli Köhler in Pyppeteer, Python

Python Cloudflare DNS A record create or update example

This is based on our previous post Python Cloudflare DNS A record update example but also creates the record if it doesn’t exist.

#!/usr/bin/env python3
import CloudFlare
import argparse
import sys

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-e", "--email", required=True, help="The Cloudflare login email to use")
    parser.add_argument("-n", "--hostname", required=True, help="The hostname to update, e.g. mydyndns.mydomain.com")
    parser.add_argument("-k", "--api-key", required=True, help="The Cloudflare global API key to use. NOTE: Domain-specific API tokens will NOT work!")
    parser.add_argument("-i", "--ip-address", required=True, help="Which IP address to update the record to")
    parser.add_argument("-t", "--ttl", default=60, type=int, help="The TTL of the records in seconds (or 1 for auto)")
    args = parser.parse_args()

    # Initialize Cloudflare API client
    cf = CloudFlare.CloudFlare(
        email=args.email,
        token=args.api_key
    )
    # Get zone ID (for the domain). This is why we need the API key and the domain API token won't be sufficient
    zone = ".".join(args.hostname.split(".")[-2:]) # domain = test.mydomain.com => zone = mydomain.com
    zones = cf.zones.get(params={"name": zone})
    if len(zones) == 0:
        print(f"Could not find CloudFlare zone {zone}, please check domain {args.hostname}")
        sys.exit(2)
    zone_id = zones[0]["id"]

    # Fetch existing A record
    a_records = cf.zones.dns_records.get(zone_id, params={"name": args.hostname, "type": "A"})
    if len(a_records): # Have an existing record
        print("Found existing record, updating...")
        a_record = a_records[0]
        # Update record & save to cloudflare
        a_record["content"] = args.ip_address
        cf.zones.dns_records.put(zone_id, a_record["id"], data=a_record)
    else: # No existing record. Create !
        print("Record doesn't existing, creating new record...")
        a_record = {}
        a_record["type"] = "A"
        a_record["name"] = args.hostname
        a_record["ttl"] = args.ttl # 1 == auto
        a_record["content"] = args.ip_address
        cf.zones.dns_records.post(zone_id, data=a_record)

Usage example:

./update-dns.py --api-key ... --email [email protected] --ttl 300 --ip 1.2.3.4 --hostname mysubdomain.domain.com

 

Posted by Uli Köhler in Networking, Python

How to reboot Netcup vServer using Python & SCP WSDL API

#!/usr/bin/env python3
from zeep import Client
import argparse

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-u", "--user", required=True, help="The Netcup SCP username. This is typically an integer like 92752")
    parser.add_argument("-p", "--password", required=True, help="The Netcup SCP webservice password. This is NOT the SCP login password")
    parser.add_argument("-v", "--vserver", required=True, help="The name of the vServer, like v2201261246567246578")
    args = parser.parse_args()

    client = Client('https://www.servercontrolpanel.de/WSEndUser?wsdl')

    print(client.service.vServerReset(args.user, args.password, args.vserver))

Call like this:

./restart-netcup-vserver.py --user 92752 --password su4ahK8ocu --vserver v2201261246567246578

 

Posted by Uli Köhler in Python

Python Cloudflare DNS A record update example

This script updates a DNS A record (IPv4 address) using the Cloudflare Python API. It expects the A record to be present already.

Also see Python Cloudflare DNS A record create or update example for a variant of this script which creates the record if it doesn’t exist already.

#!/usr/bin/env python3
import CloudFlare
import argparse
import sys

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("-e", "--email", required=True, help="The Cloudflare login email to use")
    parser.add_argument("-n", "--hostname", required=True, help="The hostname to update, e.g. mydyndns.mydomain.com")
    parser.add_argument("-k", "--api-key", required=True, help="The Cloudflare global API key to use. NOTE: Domain-specific API tokens will NOT work!")
    parser.add_argument("-i", "--ip-address", required=True, help="Which IP address to update the record to")
    parser.add_argument("-t", "--ttl", default=60, type=int, help="The TTL of the records in seconds (or 1 for auto)")
    args = parser.parse_args()

    # Initialize Cloudflare API client
    cf = CloudFlare.CloudFlare(
        email=args.email,
        token=args.api_key
    )
    # Get zone ID (for the domain). This is why we need the API key and the domain API token won't be sufficient
    zone = ".".join(args.hostname.split(".")[-2:]) # domain = test.mydomain.com => zone = mydomain.com
    zones = cf.zones.get(params={"name": zone})
    if len(zones) == 0:
        print(f"Could not find CloudFlare zone {zone}, please check domain {args.hostname}")
        sys.exit(2)
    zone_id = zones[0]["id"]

    # Fetch existing A record
    a_record = cf.zones.dns_records.get(zone_id, params={"name": args.hostname, "type": "A"})[0]

    # Update record & save to cloudflare
    a_record["ttl"] = args.ttl # 1 == auto
    a_record["content"] = args.ip_address
    cf.zones.dns_records.put(zone_id, a_record["id"], data=a_record)

Usage example:

./update-dns.py --api-key ... --email [email protected] --ttl 300 --ip 1.2.3.4 --hostname mysubdomain.domain.com

 

Posted by Uli Köhler in Networking, Python

How to find array index closest to a given value using NumPy

Let’s say you have an 1D array like

arr = np.linspace(0, 10, 100)

and you wanted to find the array index where the value is closest to 8.5.

You can do this by first computing the absolute difference to 8.5:

np.abs(arr - 8.5)

and now using np.argmin to find the array index where the value is minimal (i.e. the index where the value of arr is closest to 8.5)

np.argmin(np.abs(arr - 8.5))

 

Posted by Uli Köhler in Python

How to create NumPy XY array from X and Y array (zip equivalent)

If you have two 1D arrays x and y of the same length n = x.shape[0] in Python, this is how you can create a shape (n, 2) array using numpy similar to the way Python’s zip does it with list objects:

xy = np.stack((x, y), axis=1)
Posted by Uli Köhler in Python

How to DC-sweep resistive voltage divider using PySpice

The following code simulates a resistive 10kΩ / 1kΩ voltage divider using PySpice using a DC sweep and can serve as a suitable starting point for simulating simple circuits. We sweep from 0V to 5V in steps of 10mV.

Also see our previous post How to simulate resistive voltage divider using PySpice for an alternate version using transient analysis:

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

circuit = Circuit("MyCircuit")
# Create voltage source: 5V DC
source = circuit.VoltageSource('in', 'in', circuit.gnd, [email protected]_V)
# Create resistor divider
r1 = circuit.R('R1', 'in', 'n1', [email protected]_kΩ)
r2 = circuit.R('R2', 'n1', circuit.gnd, [email protected]_kΩ)
# Simulate for 1 second with steps of 1 millisecond
simulator = circuit.simulator(temperature=25, nominal_temperature=25)
analysis = simulator.dc(Vin=slice(0, 5.0, 0.01))

You can access the array of output voltages of the divider (i.e. node n1) using analysis['n1']Keep in mind that if the first argument of circuit.VoltageSource is 'in', the argument to simulator.dc will be valled Vin,  not just  in! A Vwill automatically be  prepended!

 

This is the code we used to plot this:

import matplotlib.ticker as mtick
import matplotlib.pyplot as plt
from UliEngineering.EngineerIO import format_value

def format_volts(value, pos=None):
    return format_value(value, 'V')

plt.style.use("ggplot")
plt.xlabel("Input voltage")
plt.xlabel("Divider output voltage")
plt.gca().yaxis.set_major_formatter(mtick.FuncFormatter(format_volts))
plt.gca().xaxis.set_major_formatter(mtick.FuncFormatter(format_volts))
plt.gcf().set_size_inches(8,5)
plt.plot(analysis["in"], analysis["n1"], label="Input voltage")
plt.savefig("/ram/PySpice-Voltage-Divider-Sweep.svg")
Posted by Uli Köhler in Electronics, Python, SPICE

How to simulate resistive voltage divider using PySpice

The following code simulates a resistive 10kΩ / 1kΩ voltage divider using PySpice and can serve as a good starting point for simulating simple circuits.

This post shows you how to simulate the voltage divider using transient analysis. Also see an alternative variant of this post using DC sweep analysis instead: How to DC-sweep resistive voltage divider using PySpice

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

circuit = Circuit("MyCircuit")
# Create voltage source: 5V DC
source = circuit.VoltageSource('V1', 'in', circuit.gnd, [email protected]_V)
# Create resistor divider
r1 = circuit.R('R1', 'in', 'n1', [email protected]_kΩ)
r2 = circuit.R('R2', 'n1', circuit.gnd, [email protected]_kΩ)
# Simulate for 1 second with steps of 1 millisecond
simulator = circuit.simulator(temperature=25, nominal_temperature=25)
analysis = simulator.transient([email protected]_ms, [email protected]_s)

You can access the array of output voltages of the divider (i.e. node n1) using analysis['n1']:

This is the code we used to plot this:

import matplotlib.ticker as mtick
import matplotlib.pyplot as plt
from UliEngineering.EngineerIO import format_value

def format_volts(value, pos=None):
    return format_value(value, 'V')

plt.style.use("ggplot")
plt.xlabel("Time [ms]")
plt.ylim([0.0, 5.5])
plt.gca().yaxis.set_major_formatter(mtick.FuncFormatter(format_volts))
plt.gcf().set_size_inches(8,5)
plt.plot(analysis["in"], label="Input voltage")
plt.plot(analysis["n1"], label="Voltage divider output")
plt.gca().legend()
plt.savefig("/ram/PySpice-Voltage-Divider.svg")

 

Posted by Uli Köhler in Electronics, Python, SPICE

How to create resistor in PySpice: Minimal example

This creates a resistor named R1 which has its + pin connected to node n1 and its - pin connected to GND. The value of the resistor is set to 1kΩ.

r1 = circuit.R('R1', 'n1', circuit.gnd, [email protected]_kΩ)

Full example:

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

circuit = Circuit("MyCircuit")
r1 = circuit.R('R1', 'n1', circuit.gnd, [email protected]_kΩ)

 

Posted by Uli Köhler in Electronics, Python, SPICE

How to create constant voltage source in PySpice

This creates a voltage source named V1 which has its + pin connected to node n1 and its - pin connected to GND. The voltage source is set to 5V DC.

source = circuit.VoltageSource('V1', 'n1', circuit.gnd, [email protected]_V)

Full example:

import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()

from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *

circuit = Circuit("MyCircuit")
source = circuit.VoltageSource('V1', 'n1', circuit.gnd, [email protected]_V)

 

Posted by Uli Köhler in Electronics, Python, SPICE