Send the contents from unmodified print statement by e-mail in python

倾然丶 夕夏残阳落幕 提交于 2020-04-18 06:12:08

问题


I have a script that runs main() and at the end I want to send the contents it has by e-mail. I don't want to write new files nor anything. Just have the original script be unmodified and at the end just send the contents of what it printed. Ideal code:

main()
send_mail()

I tried this:


def main():
  print('HELLOWORLD')

def send_email(subject='subject', message='', destination='me@gmail.com', password_path=None):
    from socket import gethostname
    from email.message import EmailMessage
    import smtplib
    import json
    import sys

    server = smtplib.SMTP('smtp.gmail.com', 587)
    smtplib.stdout = sys.stdout # <<<<<-------- why doesn't it work?
    server.starttls()
    with open(password_path) as f:
        config = json.load(f)
        server.login('me@gmail.com', config['password'])

        # craft message
        msg = EmailMessage()

        #msg.set_content(message)
        msg['Subject'] = subject
        msg['From'] = 'me@gmail.com'
        msg['To'] = destination
        # send msg
        server.send_message(msg)

if __name__ == '__main__':
    main()
    send_mail()

but it doesn't work.

I don't want to write other files or change the original python print statements. How to do this?


I tried this:

def get_stdout():
    import sys

    print('a')
    print('b')
    print('c')

    repr(sys.stdout)

    contents = ""
    #with open('some_file.txt') as f:
    #with open(sys.stdout) as f:
    for line in sys.stdout.readlines():
        contents += line
    print(contents)

but it does not let me read sys.stdout because it says its not readable. How can I open it in readable or change it to readable in the first place?


I checked all of the following links but none helped:

  • How to send output from a python script to an email address
  • https://www.quora.com/How-can-I-send-an-output-from-a-Python-script-to-an-email-address
  • https://bytes.com/topic/python/answers/165835-email-module-redirecting-stdout
  • Redirect stdout to a file in Python?
  • How to handle both `with open(...)` and `sys.stdout` nicely?
  • Capture stdout from a script?

回答1:


To send e-mails I am using:

def send_email(subject, message, destination, password_path=None):
    from socket import gethostname
    from email.message import EmailMessage
    import smtplib
    import json

    server = smtplib.SMTP('smtp.gmail.com', 587)
    server.starttls()
    with open(password_path) as f:
        config = json.load(f)
        server.login('me123@gmail.com', config['password'])
        # craft message
        msg = EmailMessage()

        message = f'{message}\nSend from Hostname: {gethostname()}'
        msg.set_content(message)
        msg['Subject'] = subject
        msg['From'] = 'me123@gmail.com'
        msg['To'] = destination
        # send msg
        server.send_message(msg)

note I have my password in a json file using an app password as suggested by this answer https://stackoverflow.com/a/60996409/3167448.

using this to collect the contents from stdout by writing it to a custom stdout file using the builtin function print:

import sys 
from pathlib import Path
def my_print(*args, filepath='~/my_stdout.txt'):
    filepath = Path(filepath).expanduser()
    # do normal print
    __builtins__['print'](*args, file=sys.__stdout__) #prints to terminal
    # open my stdout file in update mode
    with open(filepath, "a+") as f:
        # save the content we are trying to print
        __builtins__['print'](*args, file=f) #saves in a file

def collect_content_from_file(filepath):
    filepath = Path(filepath).expanduser()
    contents = ''
    with open(filepath,'r') as f:
        for line in f.readlines():
            contents = contents + line
    return contents

Note the a+ to be able to create the file if it already does NOT exist.

Note that if you want to delete the old contents of your custom my_stdout.txt you need to delete the file and check if it exists:

    # remove my stdout if it exists
    os.remove(Path('~/my_stdout.txt').expanduser()) if os.path.isfile(Path('~/my_stdout.txt').expanduser()) else None

The credits for the print code are from the answer here: How does one make an already opened file readable (e.g. sys.stdout)?



来源:https://stackoverflow.com/questions/61049796/send-the-contents-from-unmodified-print-statement-by-e-mail-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!