Figure.show() не показывает

avatar
Nico Schlömer
1 июля 2021 в 18:45
234
2
0

Я поддерживаю модный пакет для построения графиков, реализующий функцию plot_foobar(). Он возвращает фигуру с графиком, чтобы пользователь мог что-то с ней сделать, например. сохранить в файл (savefig()) или показать. К сожалению, show() ничего не делает.

MWE:

def plot_foobar():
    # fancy plotting routing in a package
    import matplotlib.pyplot as plt

    fig = plt.figure()
    plt.plot([1, 2], [3, 4])
    return fig


# the user invokes the plotting function and gets back the figure object
fig = plot_foobar()

# saving the file works
# fig.savefig("out.png")

# :(
fig.show()

# works, but is clumsy:
# import matplotlib.pyplot as plt
# plt.show()

Это предназначено?

Если да, я мог бы, конечно, попросить пользователя импортировать matplotlib и позвонить plt.show() самой - это работает. Я бы предпочел не раскрывать эту информацию и не заставлять пользователя импортировать что-то только для показа рисунка. Есть ли какой-то другой объект, который я мог бы вернуть, на котором работает show(), savefig() и т. д.?

Источник
Jody Klymak
1 июля 2021 в 18:50
2

Pyplot — это место, где запускается графический интерфейс, который может отображать что угодно, поэтому невозможно «показать», если у вас не запущен графический интерфейс. Matplotlib понимает, что это глупо, и работает над небольшой перестройкой этой архитектуры, но это займет некоторое время.

Nico Schlömer
2 июля 2021 в 07:18
0

Спасибо Джоди за ответ. Я не совсем понял, где запускается графический интерфейс. В import matplotlib.pyplot? И есть ли отчет об ошибке / проблема, за которой я могу следить в отношении перезаписи?

Jody Klymak
2 июля 2021 в 14:11
1

Я думаю github.com/matplotlib/matplotlib/pull/18852

Nico Schlömer
2 июля 2021 в 14:57
0

Более свежий отчет об ошибке: github.com/matplotlib/matplotlib/issues/19956

Ответы (2)

avatar
Nico Schlömer
11 августа 2021 в 18:19
0

Фундаментальная проблема здесь заключается в том, что matplotlib "show loop" является глобальным объектом. Есть некоторые попытки заставить fig.show() действительно что-то делать, но это не за горами. На данный момент можно вернуть глобальный объект plt

.
def plot_foobar():
    # fancy plotting routing in a package
    import matplotlib.pyplot as plt

    fig = plt.figure()
    plt.plot([1, 2], [3, 4])
    return plt

Для пользователя это ничем не отличается от fig тем, что он может plt.show() или выполнить любое другое действие над текущей фигурой.

avatar
Syler
1 июля 2021 в 19:27
0

Вы можете добавить декоратор к экземпляру Figure для вызова plt.show() внутри него:

def show_figure(f):
    '''
    Decorator to change fig.show() behavior.
    '''
    def wrapper():
        import matplotlib.pyplot as plt
        f()  # call the original fig.show(), remove this line if there is no need to run fig.show()
        plt.show()

    return wrapper

def plot_foobar():
    # fancy plotting routing in a package
    import matplotlib.pyplot as plt

    fig = plt.figure()
    plt.plot([1, 2], [3, 4])

    fig.show = show_figure(fig.show)  # assign a decorator

    return fig

# the user invokes the plotting function and gets back the figure object
fig = plot_foobar()
fig.show()