In the end, this is the best I could come up with with the help of other answers here and elsewere is this:

On the left, x and y vary over only a part of an order of magnitude, with labels working out fairly well. On the left, x varies between 1 and 2 orders of magnitude. It works okay, but the method is reaching it's limit. The y values vary many orders of magnitude and the standard labels are used automatically.
from matplotlib import ticker
from numpy import linspace, logspace, log10, floor
from warnings import warn
def round_to_n(x, n):
    ''' http://stackoverflow.com/questions/3410976/how-to-round-a-number-to-significant-figures-in-python '''
    return round(x, -int(floor(log10(abs(x)))) + (n - 1))
def ticks_log_format(value, index):
    ''' http://stackoverflow.com/questions/19239297/matplotlib-bad-ticks-labels-for-loglog-twin-axis '''
    pwr = floor(log10(value))
    base = value / (10 ** pwr)
    if pwr == 0 or pwr == 1:
        return '${0:d}$'.format(int(value))
    if -3 <= pwr < 0:
        return '${0:.3g}$'.format(value)
    if 0 < pwr <= 3:
        return '${0:d}$'.format(int(value))
    else:
        return '${0:d}\\times10^{{{1:d}}}$'.format(int(base), int(pwr))
def calc_ticks(domain, tick_count, equidistant):
    if equidistant:
        ticks = logspace(log10(domain[0]), log10(domain[1]), num = tick_count, base = 10)
    else:
        ticks = linspace(domain[0], domain[1], num = tick_count)
    for n in range(1, 6):
        if len(set(round_to_n(tick, n) for tick in ticks)) == tick_count:
            break    
    return list(round_to_n(tick, n) for tick in ticks)
''' small domain log ticks '''
def sdlt_x(ax, domain, tick_count = 4, equidistant = True):
    ''' http://stackoverflow.com/questions/3410976/how-to-round-a-number-to-significant-figures-in-python '''
    if min(domain) <= 0:
        warn('domain %g-%g contains values lower than 0' % (domain[0], domain[1]))
        domain = [max(value, 0.) for value in domain]
    ax.set_xscale('log')
    ax.set_xlim(domain)
    ax.xaxis.set_major_formatter(ticker.FuncFormatter(ticks_log_format))
    if log10(max(domain) / min(domain)) > 1.7:
        return
    ticks = calc_ticks(domain, tick_count = tick_count, equidistant = equidistant)
    ax.set_xticks(ticks)
''' any way to prevent this code duplication? '''
def sdlt_y(ax, domain, tick_count = 5, equidistant = True):
    ''' http://stackoverflow.com/questions/3410976/how-to-round-a-number-to-significant-figures-in-python '''
    if min(domain) <= 0:
        warn('domain %g-%g contains values lower than 0' % (domain[0], domain[1]))
        domain = [max(value, 1e-8) for value in domain]
    ax.set_yscale('log')
    ax.set_ylim(domain)
    ax.yaxis.set_major_formatter(ticker.FuncFormatter(ticks_log_format))
    if log10(max(domain) / min(domain)) > 1.7:
        return
    ticks = calc_ticks(domain, tick_count = tick_count, equidistant = equidistant)
    ax.set_yticks(ticks)
''' demo '''
fig, (ax1, ax2,) = plt.subplots(1, 2)
for mi, ma, ax in ((100, 130, ax1,), (10, 400, ax2,), ):
    x = np.linspace(mi, ma, 50)
    y = 1 / ((x + random(50) * 0.1 * (ma - mi)) ** 4)
    ax.scatter(x, y)
    sdlt_x(ax, (mi, ma, ))
    sdlt_y(ax, (min(y), max(y), ))
show()
EDIT: updated with an option to make labels equidistant (so the values are logarithmic, but the visible positions are equidistant).