Запись вывода функции в текстовый файл

Я хочу записать содержимое кадра данных pandas в текстовый файл. Это образец фрейма данных, с которым я работаю:

last_week = pd.date_range(start=(datetime.today() - timedelta(weeks=1)), end=datetime.today()).map(lambda x: x.strftime('%Y-%m-%d'))

df = pd.DataFrame(index=pd.MultiIndex.from_product([list(last_week), ['A', 'B', 'C']]),
                  data={'Category 1':np.random.randint(100, size=24),
                        'Category 2':np.random.randint(100, size=24)})

df.index = df.index.set_levels([pd.to_datetime(df.index.levels[0], format='%Y-%m-%d'), df.index.levels[1]])
df.index.set_names(['Day', 'App Name'], level=[0,1], inplace=True)

Я написал функцию, которая выводит содержимое фрейма данных в нужном мне формате:

def write_to_file():
    for n in df.reset_index().index:
        row = df.reset_index().iloc[n]
        row = row[row.notnull()]

        print(f"""
\tDay: {datetime.strftime(row.loc['Day'], '%Y-%m-%d')}
\tApp: {row.loc['App Name']}""")

        for i in row.index[2:]:
            print(f"\t{i}: {round(row.loc[i], 2)}")

Когда я вызываю эту функцию, она выводит следующее:

    Day: 2020-02-13
    App: A
    Category 1: 6
    Category 2: 73

    Day: 2020-02-13
    App: B
    Category 1: 39
    Category 2: 41

    Day: 2020-02-13
    App: C
    Category 1: 15
    Category 2: 15

    Day: 2020-02-14
    App: A
    Category 1: 26
    Category 2: 8

    Day: 2020-02-14
    App: B
    Category 1: 72
    Category 2: 8

    Day: 2020-02-14
    App: C
    Category 1: 62
    Category 2: 32

    Day: 2020-02-15
    App: A
    Category 1: 76
    Category 2: 21

    Day: 2020-02-15
    App: B
    Category 1: 35
    Category 2: 19

Однако, когда я пытаюсь записать вывод функции в файл...

with open('./filepath', 'w') as f:
    f.write(write_to_file())

это не работает, потому что вывод функции - Nonetype. Может ли кто-нибудь предложить способ записи этого вывода в файл?

Спасибо!


person James D.    schedule 20.02.2020    source источник


Ответы (2)


Причина, по которой ваш f.write() не работает, заключается в том, что write_to_file() выводит с использованием print(). print() записывает то, что мы называем «стандартным выводом» или сокращенно stdout. По умолчанию stdout — это терминал, на котором вы запускаете свою программу.

Операционные системы позволяют перенаправлять стандартный вывод в файл. Вы делаете это с помощью следующей команды:

python program.py > output.txt

Когда вы сделаете это, вы не увидите никакого вывода в своей консоли. Вместо этого вы можете открыть файл output.txt после того, как программа закончит работу, и увидеть там результат.

Преимущество этого решения в том, что оно работает без каких-либо изменений в вашем коде Python. Это также общий стандарт для программ командной строки. Кроме того, вы можете записать в файл из своего кода Python. Для этого необходимо открыть файл, как вы знаете, как это сделать. Затем вам нужно вызвать f.write() вместо print():

def write_to_file():
    with open('output.txt') as f:
        for n in df.reset_index().index:
            row = df.reset_index().iloc[n]
            row = row[row.notnull()]

            f.write(f"""
\tDay: {datetime.strftime(row.loc['Day'], '%Y-%m-%d')}
\tApp: {row.loc['App Name']}""")

            for i in row.index[2:]:
                f.write(f"\t{i}: {round(row.loc[i], 2)}")

Чтобы сделать эту функцию более гибкой, вы можете добавить параметр для имени файла вместо того, чтобы всегда писать в output.txt. Это изменение оставлено читателю в качестве упражнения.

person Code-Apprentice    schedule 20.02.2020
comment
Спасибо за ваш ответ. Я также добавил дополнительный параметр, позволяющий пользователю выбирать путь к файлу, как вы предложили. - person James D.; 21.02.2020

Вместо того, чтобы печатать свой вывод в write_to_file(), вам нужно вернуть строку, чтобы вы могли вывести ее в файл. Если это потенциально длинная строка, см. эту статью об эффективной конкатенации строк в python.

person jarthur    schedule 20.02.2020