Archive

Archive for June, 2019

force requests to use IPv4

June 28, 2019 Leave a comment

Problem
I have a script that periodically calls the API of a server to fetch some data. It worked well under Manjaro and Ubuntu. However, after a system update, the script stopped working on Ubuntu.

Diagnosis
It turned out that requests.get() couldn’t connect to the server. I tried to ping the host and under Ubuntu ping resolved an IPv6 address and it was unreachable. You can force ping to use IPv4 with the “-4” switch (ex.: “ping example.com -4“). Under Manjaro ping resolved an IPv4 address by default and the Python script worked well. Under Ubuntu, however, requests.get() wanted to use IPv6 and for some reason the given host was not reachable through that protocol.

Solution
In my Python code I used the following patch to force the usage of IPv4. requests relies on a lower level library, urllib3, thus the urllib3 part had to be patched:

import socket
import requests.packages.urllib3.util.connection as urllib3_cn

def allowed_gai_family():
    family = socket.AF_INET    # force IPv4
    return family

urllib3_cn.allowed_gai_family = allowed_gai_family

It solved the issue under Ubuntu. This tip is from here.

Categories: python Tags: , , , , ,

APScheduler3 examples

June 26, 2019 Leave a comment

A long time ago (in 2013) I wrote a post about APScheduler, see here. Since then a new version of APScheduler has come out, so it was time to update that old post.

So, the examples below were tested with APScheduler 3.6. The source code of the examples can be found on GitHub too (here).

#!/usr/bin/env python3

import os
from apscheduler.schedulers.blocking import BlockingScheduler
import mylogging as log

sched = BlockingScheduler()


@sched.scheduled_job('interval', minutes=60)
def once_per_hour():
    """
    If you lauch this script at time T, then this function will be called
    at T+60 minutes for the first time.
    Ex.: if you lauch the script at 13h07, then this function will be called at 14h07
    for the first time.
    """
    log.info('calling once_per_hour')


@sched.scheduled_job('interval', minutes=2)
def once_per_hour():
    """
    Call it every 2 minutes.
    """
    log.info('2 minutes passed')


@sched.scheduled_job('cron', hour='*/4', minute=2)
def four_hours():
    """
    Run this function every four hour + 2 minutes.
    Ex.: it's called at 00h02, 04h02, 08h02, etc.
    """
    log.info('calling four_hours')


@sched.scheduled_job('cron', day='*', hour=0, minute=5)
def daily_backup():
    """
    Run it once a day at 5 minutes after midnight.

    !!! If it takes time, then don't do the work here because the work
    here will block the calling of the other functions! If it takes time, then
    simply launch the work in the background. Here the slow work is collected in
    a batch file and the batch file is launched in the background.
    """
    log.info('calling daily_backup')
    os.system("./daily_backup.sh &")


@sched.scheduled_job('cron', day='*', hour=0)
def midnight():
    """
    Call it at midnight.
    """
    log.info('calling midnight')


@sched.scheduled_job('cron', day='*', hour=18)
@sched.scheduled_job('cron', day='*', hour=19)
@sched.scheduled_job('cron', day='*', hour=20)
def triple_check():
    """
    Call this function every day at 18h00, 19h00 and 20h00.
    """
    log.info('calling triple_check')


@sched.scheduled_job('cron', day_of_week='wed', hour=19, minute=0)
@sched.scheduled_job('cron', day_of_week='sun', hour=19, minute=0)
def mini_backup():
    """
    Call this function on Wednesday at 19h00 and
    on Sunday at 19h00.
    """
    log.info('calling mini_backup')


def main():
    log.info('the scheduler is running...')
    sched.start()

##############################################################################

if __name__ == "__main__":
    main()

Find the complete source code on GitHub (here).

Categories: python Tags: , , ,