Programming languages

How to install PyPy3 + virtual environment in 30 seconds

TL;DR:

Run this

wget -qO- https://techoverflow.net/scripts/pypy3-installer.sh | bash

then run vpypy every time you want to activate (you might need to restart). The script currently assumes you are running Linux x86_64 and have installed virtualenv (sudo apt install virtualenv or similar if you don’t have it installed)

Full description:

PyPy is an alternate Python implementation that can be used to speed up many workloads. However, installing it is a somewhat cumbersome process, especially if you don’t have too much experience with virtual environments and related concepts.

We provide a script that automatically downloads PyPy3, installs it to ~/.pypy3 and creates a virtual environment in ~/.pypy3-virtualenv. After that, it creates a shell alias vpypy that aliases to source ~/.pypy3-virtualenv/bin/activate and hence provides an easily memoizable way of activating the environment without requiring the user to memoize the directory.

Also, since both pypy3 itself and the virtual environment are  installed in the user’s home directory, running this script does not require admin permissions.

After running the script using

wget -qO- https://techoverflow.net/scripts/pypy3-installer.sh | bash

you can activate the virtual environment using the vpypy alias that is automatically added to ~/.bashrc and ~/.zshrc. Restart your shell for the alias definition to load, then run vpypy:

uli@uli-laptop ~ % vpypy
(.pypy3-virtualenv) uli@uli-laptop ~ % 

You can see that the prompt has changed. Now you can use pip (which will install packages locally to the PyPy3 virtualenv), python (which maps to pypy3) and other related executables. In order to run a script using PyPy, just run python myscript.py

Full source code:

#!/bin/bash
# TechOverflow's 30-second Pypy3 virtual environment generator
# This script is released under CC0 1.0 Universal
DIRECTORY=~/.pypy3
VENV_DIRECTORY=~/.pypy3-virtualenv
VERSION=pypy3.6-v7.3.0-linux64

# Download (or use existing) pypy3
if [ -d "$DIRECTORY" ]; then
    echo "Skipping PyPy download, already exists"
else
    echo "Downloading PyPy to $DIRECTORY"
    # Download & extract to DIRECTORY
    wget https://techoverflow.net/downloads/${VERSION}.tar.bz2 -O /tmp/${VERSION}.tar.bz2
    bash -c "cd /tmp && tar xjvf ${VERSION}.tar.bz2"
    mv /tmp/${VERSION} $DIRECTORY
    rm /tmp/${VERSION}.tar.bz2
fi

# Create virtualenv
if [ -d "$VENV_DIRECTORY" ]; then
    echo "Skipping to create pypy3 virtualenv, already exists"
else
    echo "Creating PyPy virtual environment in $VENV_DIRECTORY"
    virtualenv -p ${DIRECTORY}/bin/pypy3 ${VENV_DIRECTORY}
fi

# Create "vpypy" shortcut
set -x
vpypy
result="$?"
set +x
if [ "$result" -ne 127 ]; then
    echo "Skipping to create vpypy shortcut, already exists in current shell"
else
    echo "Creating bash/zsh shortcut 'vpypy'"
    if [ -f ~/.bashrc ]; then
        echo -e "\n# TechOverflow PyPy installer\nalias vpypy='source ${VENV_DIRECTORY}/bin/activate'\n" >> ~/.bashrc
    fi
    if [ -f ~/.zshrc ]; then
        echo -e "\n# TechOverflow PyPy installer\nalias vpypy='source ${VENV_DIRECTORY}/bin/activate'\n" >> ~/.zshrc
    fi
    # Activate shortcut in current shell (but do not automatically activate virtual environment)
    alias vpypy='source ${VENV_DIRECTORY}/bin/activate'
fi

echo -e "\n\nPyPy installation finished. Restart your shell, then run 'vpypy' to activate the virtual environment"

 

 

Posted by Uli Köhler in Linux, Python

How to decompress gzip files using zlib – a minimal example

zlib is a great library in use by hundreds of thousands of programs (including Python). However, it lacks documentation.

This minimal example shows you how to create a simple zcat-like program that decompresses a gzipped input file and prints its contents to stdout.

/**
 * zzcat.c -- Minimal gzip decompression example using zlib
 * Written by Uli Köhler (techoverflow.net).
   Not copyrighted -- provided to the public domain
 */
#include <stdio.h>
#include <zlib.h>

#define BUFSIZE 16384

/* compress or decompress from fin (command line argument) to stdout */
int main(int argc, char **argv)
{
    if(argc <= 1) { // <= (number of expected CLI arguments)
        fprintf(stderr, "Usage: %s <input file>\n", argv[0]);
        return -1;
    }

    gzFile fin = gzopen(argv[1], "rb");

    char buf[BUFSIZE];
    int n;

    while((n = gzread(fin, buf, BUFSIZE)) > 0) {
        fwrite(buf, 1, n, stdout);
    }

    return 0;
}

Compile using

g++ -o zzcat zzcat.c -lz

Usage example:

# Create test file
echo "foo" | gzip -c > test.txt.gz
# Uncompress using zzcat! 
./zzcat test.txt.gz # This will print "foo"

 

Posted by Uli Köhler in C/C++

C/C++ program template with one CLI argument

This example program provides an example of a CLI executable in C/C++ that uses one command line argument and exits with a usage message if that argument is not present:

#include <stdio.h>

int main(int argc, char **argv)
{
    if(argc <= 1) { // <= (number of expected CLI arguments)
        fprintf(stderr, "Usage: %s <input file>\n", argv[0]);
        return -1;
    }
    
    // TODO Your code goes here!
    printf("Input file: %s\n", argv[1]);
    return 0;
}

Compile with

g++ -o cli-onearg cli-onearg.cpp

Usage example:

$ ./cli-onearg  
Usage: ./cli-onearg <input file>
$ ./cli-onearg my-input-file.txt
Input file: my-input-file.txt

 

Posted by Uli Köhler in C/C++

How to fix /usr/bin/ld: cannot find -lzlib

Problem:

You want to compile a C++ executable that uses zlib, but you see an error message like

/usr/bin/ld: cannot find -lzlib
collect2: error: ld returned 1 exit status

Solution:

Use -lz instead of -lzlib. The zlib library is named libz.so, not libzlib.so!

Example:

g++ -o ztest zpipe.c -lz

 

Posted by Uli Köhler in C/C++

How to fill matrix with NaN in Octave

Also see: How to initialize NaN matrix in octave

If you have a matrix in Octave like

A = zeros(2,4)

you can fill it with NaN using

A(:,:) = NaN

Note that you have to use A(:) = NaN for 1D-matrices. A(:,:) = NaN for 2D matrices, A(:,:,:) = NaN for 3D matrices and so on.

Example:

>> A = zeros(2,4)
A =

   0   0   0   0
   0   0   0   0

>> A(:,:) = NaN
A =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

 

Posted by Uli Köhler in Octave

How to initialize NaN matrix in octave

Also see: How to fill matrix with NaN in Octave

You can use NaN(N,M) as a function to initialize a NxM matrix filled with NaN in octave. For example, to initialize a 2x4x3 matrix, use

A = NaN(2,4,3)

Example:

>> A = NaN(2,4,3)
A =

ans(:,:,1) =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

ans(:,:,2) =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN

ans(:,:,3) =

   NaN   NaN   NaN   NaN
   NaN   NaN   NaN   NaN
Posted by Uli Köhler in Octave

How to remove all event listeners from a DOM element in Javascript

You can remove all event listeners from a DOM element in Javascript by replacing the element with a deep clone of itself. elem.cloneNode(...) will not clone the event listeners of the source element.

elem.replaceWith(elem.cloneNode(true));

Full example:

var elem = document.getElementById('mybutton');
elem.replaceWith(elem.cloneNode(true));

Source for the original (partial) suggestion on StackOverflow: @Felix Kling

Posted by Uli Köhler in Javascript

How to remove dashicons CSS from WordPress

WordPress uses dashicons as its primary icon font. However, many themes do not require dashicons on the frontend and hence it’s only used in the admin frontend, i.e. when a user is logged in.

I made a simple plugin to make WordPress load the dashicons CSS only if the user is logged in. For non-logged-in users, the dashicons CSS is removed from the frontend (hence improving the loading speed of your website).

<?php 
/*
Plugin Name: TechOverflow remove dashicons
*/

/**
 * Remove dashicons CSS from the page, only load if user is logged in
 */
function dashicons_admin_only() {
    if(!is_user_logged_in()) {
        global $wp_styles;
        wp_dequeue_style('dashicons');
        // wp_deregister_style('dashicons') causes internal PHP errors in WordPress !
        $wp_styles->registered['dashicons']->src = '';
    }
}
    
add_action( 'wp_print_styles', 'dashicons_admin_only' );

Just create an new folder called techoverflow-no-dashicons inside your wp-content/plugins directory, and save the source code listed above as wp-content/plugins/techoverflow-no-dashicons/functions.php inside. After that, you can modify the code to fit your specific needs.

Note that using this plugin might make your site appear differently if you are logged in. Hence it’s important to check your site when not logged in, e.g. using incognito mode.

Posted by Uli Köhler in PHP, Wordpress

WordPress: How to move script to footer if plugin doesn’t support it

Many WordPress plugins provide you with an option to configure whether scripts are loaded in the header or the footer of the page.

If you want to move a script to the footer for performance reasons, and the plugin doesn’t support it, one option is to just edit the wp_enqueue_script() call in the plugin’s source code and set $in_footer = true.

However, these change won’t survive plugin updates and hence are not recommended for security reasons.

A better option is to write a custom plugin that removes the <script> tag from the head and moves it to the footer. The following file is the functions.php of my custom plugin that moves the <script> tag from the cookie-law-info plugin to the bottom of the page.

<?php 
/*
Plugin Name: TechOverflow Cookie Law to footer
*/

function postpone_script($name) {
    global $wp_scripts;
    // Get attributes from original script
    $thesrc = $wp_scripts->registered[$name]->src;
    $theversion = $wp_scripts->registered[$name]->ver;
    // Remove script from the header
    wp_dequeue_script($name);
    wp_deregister_script($name);
    // Add script to the bottom
    wp_enqueue_script($name, $thesrc, false /* no deps */, $theversion, true /* bottom */);
}

/**
 * Move cookie law javascript to the bottom
 */
function postpone_cookie_law() {
    postpone_script('cookie-law-info');
}
    
add_action( 'wp_print_scripts', 'postpone_cookie_law' );

Just create an new folder called techoverflow-cookie-law-footer inside your wp-content/plugins directory, and save the source code listed above as wp-content/plugins/techoverflow-cookie-law-footer/functions.php inside. After that, you can modify the code to fit your specific needs.

Remember to check your page for issues (javascript errors, delayed rendering of some elements) that appear when you move the javascript to the footer, since some plugins may not be compatible with the script being placed in the footer. Also, you might need to call postpone_script() multiple scripts with different $name argument. Check the original plugin’s wp_enqueue_script() calls for the correct $name (first argument). In case it’s not obvious which wp_enqueue_script() call relates to a specific script, you can also check the version in the src of the original <script> tag (e.g. 1.8.2 in ...?ver=1.8.2 ) and search for that version in the plugin’s folder to find the matching wp_enqueue_script() call.

Posted by Uli Köhler in PHP, Wordpress

WordPress: Enqueue script only if user is logged in

Use this snippet in your wordpress plugin to load a script only if a user is logged in:

function enqueue_my_script() {
    if(is_user_logged_in()) {
        wp_enqueue_script( 'my-script', plugins_url('/my-script.js', __FILE__), false, '1.0', 'all');
    }
}

add_action( 'wp_enqueue_scripts', 'enqueue_my_script');

It does not matter how exactly you use wp_enqueue_script(), just wrap it in a

if(is_user_logged_in()) {
    // Call wp_enqueue_script() here !
}

 

Posted by Uli Köhler in PHP, Wordpress

How to copy a 2D matrix to a slice of a 3D matrix in Octave

In our previous post we showed how to create a 3D matrix in Octave, for example this 2x4x3 matrix:

>> A = zeros(2, 4, 3);
>> A
A =

ans(:,:,1) =

   0   0   0   0
   0   0   0   0

ans(:,:,2) =

   0   0   0   0
   0   0   0   0

ans(:,:,3) =

   0   0   0   0
   0   0   0   0

What if we want to copy a 2D matrix slice like

>> B = ones(2, 4)
B =

   1   1   1   1
   1   1   1   1

to the 3D matrix?

First, we need to think about which matrix indices we need to copy to.
Obviously, since B is a 2x4 matrix and A is a 2x4x3 matrix, the third dimension needs to be fixed since the size of the first and second dimension of A is identical to the dimension of B.

Hence we can copy B to either

  • A(:,:,1) or
  • A(:,:,2) or
  • A(:,:,3)

For example, we can copy B to A(:,:,2) using

A(:,:,2) = B

In our example with B = ones(2,4) and A = zeros(2,4,3) will look like this:

>> A(:,:,2) = B
A =

ans(:,:,1) =

   0   0   0   0
   0   0   0   0

ans(:,:,2) =

   1   1   1   1
   1   1   1   1

ans(:,:,3) =

   0   0   0   0
   0   0   0   0

 

Posted by Uli Köhler in Octave

How to create a 3D matrix in Octave

In order to create a X*Y*Z-sized 3D matrix in Octave, use

A = zeros(X, Y, Z);

For example, to create a 5x6x3 matrix, use

A = zeros(5, 6, 3);

zeros() initializes the matrix to 0:

>> A = zeros(5, 6, 3);
>> A
A =

ans(:,:,1) =

   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0

ans(:,:,2) =

   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0

ans(:,:,3) =

   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0
   0   0   0   0   0   0

 

Posted by Uli Köhler in Octave

Is pypng 16-bit PNG encoding faster using pypy on the Raspberry Pi?

In our previous post How to save Raspberry Pi raw 10-bit image as 16-bit PNG using pypng we investigated how to use the pypng library to save 10-bit raw Raspberry Pi Camera images to 16-bit PNG files.

However, saving a single image took ~26 seconds using CPython 3.7.3. Since pypy can provide speedups to many Python workloads, we tried using pypy3 7.0.0 (see How to install pypy3 on the Raspberry Pi) to speed up the PNG encoding.

Results

pypng PNG export seems to be one of the workloads that are much slower using pypy3.

  • CPython 3.7.3: Encoding took 24.22 seconds
  • pypy3 7.0.0: Encoding took 266.60 seconds

Encoding is more that 10x slower when using pypy3!

Hence I don’t recommend using pypy3 to speed up pypng encoding workloads, at least not on the Raspberry Pi!

Full example

This example is derived from our full example previously posted on How to save Raspberry Pi raw 10-bit image as 16-bit PNG using pypng:

#!/usr/bin/env python3
import time
import picamera
import picamera.array
import numpy as np
import png

# Capture image
print("Capturing image...")
with picamera.PiCamera() as camera:
    with picamera.array.PiBayerArray(camera) as stream:
        camera.capture(stream, 'jpeg', bayer=True)
        # Demosaic data and write to rawimg
        # (stream.array contains the non-demosaiced data)
        rawimg = stream.demosaic()

# Write to PNG
print("Writing 16-bit PNG...")
t0 = time.time()
with open('16bit.png', 'wb') as outfile:
    writer = png.Writer(width=rawimg.shape[1], height=rawimg.shape[0], bitdepth=16, greyscale=False)
    # rawimg is a (w, h, 3) RGB uint16 array
    # but PyPNG needs a (w, h*3) array
    png_data = np.reshape(rawimg, (-1, rawimg.shape[1]*3))
    # Scale 10 bit data to 16 bit values (else it will appear black)
    # NOTE: Depending on your photo and the settings,
    #  it might still appear quite dark!
    png_data *= int(2**6)
    writer.write(outfile, png_data)
t1 = time.time()

print(f"Encoding took {(t1 - t0):.2f} seconds")

 

Posted by Uli Köhler in Python, Raspberry Pi

How to install pypy3 on the Raspberry Pi

This post shows you an easy way of getting pypy3 running on the Raspberry Pi. I used Raspbian Buster on a Raspberry Pi 3 for this example. On Raspbian buster this will install pypy3 7.x!

First install pypy3 and virtualenv:

sudo apt update && sudo apt -y install pypy3 pypy3-dev virtualenv

Now we can create a virtualenv to install pypy packages into:

virtualenv -p /usr/bin/pypy3 ~/pypy3-virtualenv

Now we can activate the virtualenv. You need to do this every time you want to use pypy, for each shell / SSH connection separately:

source ~/pypy3-virtualenv/bin/activate

If your shell prompt is now prefixed by (pypy3-virtualenv) you have successfully activated the virtualenv:

(pypy3-virtualenv) uli@raspberrypi:~ $

Now python points to pypy3 and pip will install packages locally to ~/pypy3-virtualenv.

Now you can use e.g.

python3 myscript.py

to run your script (both python and python3 will point to pypy3 if you activated the virtual environment!).

Note: Installing pypy3-dev is not strictly neccessary to get pypy3 running, but you need it in order to compile native librarie like numpy.

Posted by Uli Köhler in Python, Raspberry Pi

How to capture RaspberryPi camera 10-bit raw image in Python

You can use the picamera Python library to capture a raw sensor image of a camera attached to the Raspberry Pi via CSI:

#!/usr/bin/env python3
import picamera
import picamera.array
import numpy as np

# Capture image
print("Capturing image...")
with picamera.PiCamera() as camera:
    with picamera.array.PiBayerArray(camera) as stream:
        camera.capture(stream, 'jpeg', bayer=True)
        # Demosaic data and write to rawimg
        # (stream.array contains the non-demosaiced data)
        rawimg = stream.demosaic()

rawimg is a numpy uint16 array of dimensions (w, h, 3), e.g. (1944, 2592, 3) and contains integer values from 0 to 1023.

You can, for example, save it in a NumPy file using

np.save("rawimg.npy", rawimg) # Reload with np.load("rawimg.npy")

or save it in a compressed format using

np.savez_compressed("rawimg.npz", rawimg) # Reload with np.load("rawimg.npz")
Posted by Uli Köhler in Python, Raspberry Pi

How to fix ModuleNotFoundError: No module named ‘picamera’

Problem:

You want to run a Python script using the Raspberry Pi camera but you see an error message like

Traceback (most recent call last):
  File "mycamera.py", line 2, in <module>
    import picamera
ModuleNotFoundError: No module named 'picamera'

Solution:

You need to install the picamera Python module using pip:

sudo pip3 install picamera

or, if you are still using Python 2.x:

sudo pip install picamera

In case you see

sudo: pip3: command not found

install pip3 using

sudo apt install -y python3-pip

 

Posted by Uli Köhler in Python, Raspberry Pi

NodeJS argparse minimal example

Install argparse using

npm i --save argparse

Optional argument:

const ArgumentParser = require('argparse').ArgumentParser;
const parser = new ArgumentParser({});
parser.addArgument(['-u', '--url'], {help: "The URL to use"});
const args = parser.parseArgs();

// Example usage
console.log(args.url) // null if no such argument

If you want to make an argument mandatory, use required: true:

const ArgumentParser = require('argparse').ArgumentParser;
const parser = new ArgumentParser({});
parser.addArgument(['-u', '--url'], {help: "The URL to use", required: true});
const args = parser.parseArgs();

// Example usage
console.log(args.url)

In case the user does not provide the argument, it will print

usage: CLI.js [-h] -u URL
CLI.js: error: Argument "-u/--url" is required

Positional arguments

This positional argument will always be required:

const ArgumentParser = require('argparse').ArgumentParser;
const parser = new ArgumentParser({});
parser.addArgument(['url'], {help: "The URL to use"});
const args = parser.parseArgs();

// Example usage
console.log(args.url)

 

Posted by Uli Köhler in Javascript, NodeJS

How to just show HTTP headers using wget

Use --server-response -qO /dev/null:

wget --server-response -qO /dev/null [URL]

Example:

wget --server-response -qO /dev/null https://techoverflow.net

Example output:

HTTP/1.1 200 OK
Server: nginx/1.14.0 (Ubuntu)
Date: Mon, 18 Nov 2019 02:15:19 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
Set-Cookie: cookielawinfo-checkbox-necessary=yes; expires=Mon, 18-Nov-2019 03:15:18 GMT; Max-Age=3600; path=/
Set-Cookie: cookielawinfo-checkbox-non-necessary=yes; expires=Mon, 18-Nov-2019 03:15:18 GMT; Max-Age=3600; path=/
Link: <https://techoverflow.net/wp-json/>; rel="https://api.w.org/"

 

Posted by Uli Köhler in Shell

gzip-compress in-memory in Go

In Go, you can use the built-in gzip library together with bytes.Buffer to compress a []byte to obtain a []byte containing gzip-compressed data:

content := "Hello World!"
buf := &bytes.Buffer{}
gzWriter := gzip.NewWriter(buf)
gzWriter.Write([]byte(content))
gzWriter.Close()

This full example compresses the data in-memory and writes it to a file called text.txt.gz afterwards. Note that you can also gzip directly into a file and if you don’t need to do anything else with the compressed data, you might as well have a look at our previous post How to write to gzipped file in Go.

package main

import (
    "compress/gzip"
    "os"
)

func main() {
    content := "Hello World!"
    // Initialize gzip
    buf := &bytes.Buffer{}
    gzWriter := gzip.NewWriter(buf)
    gzWriter.Write([]byte(content))
    gzWriter.Close()
    // Convert buffer to
    ioutil.WriteFile("test.txt.gz", buf.Bytes(), 0644)
}

You can use zcat test.txt.gz to see that the content has been written to the file correctly.

Posted by Uli Köhler in Go

How to write to gzipped file in Go

This example shows you how to directly write gzip-compressed data using Go’s gzip library.

First, open the file and use gzip.NewWriter() to create a new io.Writer on it:

// Open file
f, _ := os.Create("test.txt.gz")
defer f.Close()
// Create gzip writer
gzWriter := gzip.NewWriter(f)

Now you can gzWriter.Write(). Don’t forget to gzWriter.Close()

content := "Hello World!"
gzWriter.Write([]byte(content))
gzWriter.Close()

Full example:

package main

import (
    "compress/gzip"
    "os"
)

func main() {
    // Open file
    f, _ := os.Create("test.txt.gz")
    defer f.Close()
    // Create gzip writer
    gzWriter := gzip.NewWriter(f)
    // Write content and close
    content := "Hello World!"
    gzWriter.Write([]byte(content))
    gzWriter.Close()
}

You can use zcat test.txt.gz to see that the content has been written to the file correctly.

Posted by Uli Köhler in Go