python add timestamp to console output - python

I would like to add a timestamp for each output in console.
My tool is using selenium and clicks on specific things on a website.
when specific events happen (for example see below code block) I would like to print it with a timestamp.
print(f'Bought player: {str_player_name} for {int_player_price}')
print(f'Estimated profit: {int_expected_profit}')
print(f'Player counter {str(int_players_bought)}/{str(int_max_players_bought)}')
I have many prints in my console - is there a way to automatically add a timestamp to each print('')?

add this to your code
from datetime import datetime
print(datetime.now().strftime(%H:%M:%S))

You could define a printf function for that too
from datetime import datetime
def printf(*arg, **kwarg):
timestamp = datetime.now().strftime("%H:%M:%S")
print(timestamp, *arg, **kwarg)
Then, replace all your print call into printf.
But what you are trying to do is the job of the logger. I suggest you should add loggers to your code before it becomes complicated.

Related

Python: get next item from a list on a schedule

This is my first posted question; I am a new coder who is trying to make a fun quiz app for a friend using Flask, Jinja, and Python. In the quiz, you get 6 different clues each day that point you towards a specific answer (not multiple choice, a specific answer). I have a list with all the answers, and I am currently trying to get the next item in the list...but the problem that I'm running into is that I want this to happen on a schedule, every 24 hours. That's the hard part: I can print the next item in the list just fine, but I can't figure out how to then automatically print the next item at a specific time interval. Once I have that I think I'll be well on my way! (I really want to do this in Python, not JavaScript, because I know even less JavaScript than I do Python).
Here's several things I've tried:
import schedule
from schedule import every, repeat
import time
answers = ["answer1", "answer2", "answer3"]
#repeat(every(3).seconds)
def fetch():
global answers
answers += 0
print(answers)
while 1:
schedule.run_pending()
time.sleep(1)
This returns the error: 'int' object is not iterable.
I have also tried:
import schedule
import time
def job():
answers = ["answer1", "answer2", "answer3"]
for answer in answers:
print(answer[0:])
schedule.every(10).seconds.do(job)
while 1:
schedule.run_pending()
time.sleep(1)
This just prints all the books at once; not what I want, I want a different one every interval (here 10 seconds, but in reality 24 hours).
Another thing I tried:
import schedule
import time
def job():
answers = ["answer1", "answer2", "answer3"]
answersIterator = iter(answers)
print(next(answersIterator))
schedule.every(10).seconds.do(job)
while 1:
schedule.run_pending()
time.sleep(1)
This just prints the first item from the list on repeat; I want it to go through the list, but not all at once, at a specific interval.
I have read through as many tutorials as I can get my hands, but because I'm new at this I'm struggling. Apologies if there are formatting issues here; I read through the guidance before posting, but first time, etc. etc. Thanks all!
Consider where you define variables and in which area they are valid. In the last attempts, for this reason, the iterators do not maintain their state. They are recreated each time the function is called and disappear again when the function is exited.
The following example defines a global iterator that starts over at the end of the sequence. Its state is preserved because it was not defined in the local scope of the function. Within your repeatedly called function you can now query the next element at regular intervals with next(iterator).
from itertools import cycle
from schedule import every, repeat, run_pending
import time
iter_answers = cycle(["answer1", "answer2", "answer3"])
#repeat(every(10).seconds)
def job():
print(next(iter_answers))
while True:
run_pending()
time.sleep(1)
However, I don't understand how you want to use the code inside Flask.
If I understood you correctly, the client should ask for an answer, which is updated and provided by the server at intervals. So you should think about how to write an endpoint that matches a timestamp and depending on that uses the next element in the sequence. So possibly something like this.
from flask import Flask
from datetime import datetime
class Provider:
def __init__(self, items):
self._i = 0
self._t = datetime.now()
self.items = items
def next(self):
if (datetime.now() - self._t).total_seconds() >= 10:
self._i = (self._i + 1) % len(self.items)
self._t = datetime.now()
return self.items[self._i]
provider = Provider([
'answer1',
'answer2',
'answer3',
])
app = Flask(__name__)
#app.route('/')
def index():
return provider.next()

How to create a Python 'alarm' which will act either today or tomorrow

I have been given a python script which allows me to mute the volume of my mac at a time I set so that any podcasts I'm listening to as I fall asleep won't wake me up once I am asleep.
However, it will only act once the time given happens on that day, therefore if I try to activate it before midnight, it will mute the laptop immediately, which is not ideal because if I want to use it I have to wait for midnight to pass before I go to sleep.
#!/usr/bin/env python3
import datetime as dt
import osascript
import sys
from threading import Timer
def do_the_biz():
osascript.osascript("set volume output volume 0")
print("Night night")
today = dt.datetime.now()
dateString = today.strftime('%d-%m-%Y') + " " + sys.argv[1]
newDate = today.strptime(dateString,'%d-%m-%Y %H:%M')
delay = (newDate - dt.datetime.now()).total_seconds()
Timer(delay,do_the_biz,()).start()
So, a typical execution of this script looks like this:
$./sleep.py 04:00
and the command line will return the following once it has reached 4am, and then close the program:
Night Night
What I would like is to be able to manipulate the date so that the script will operate at the next available time of, for example, 4am - so it would essentially operate almost in the exact same way an alarm would. For this I could run an entirely different script of sleep.tomorrow.
However, in an ideal world, I would like to be able to:
have the option to have another argument where I specify today or tomorrow and the program acts accordingly;
be able to cancel the process without having to close the terminal.
I am new to python and have been having a hard time understanding the differences between the various datetime functions and the documention hasn't helped, so a brief explanation and comparison between what they input and output and how they interact would be gratefully appreciated.

printing to multiple lines at the same time python

I am making a text based game and I am trying to print this code one character at a time on each column.
'''###############
Let us begin...
###############'''
I can't figure out how to make it come out one column at a time.
Well, I still felt like answering this despite the vagueness of your question. Maybe this is what you are looking for, this prints one column at a time (one character per row):
import subprocess
import platform
from time import sleep
def clear_screen():
# thanks to: https://stackoverflow.com/a/23075152/2923937
if platform.system() == "Windows":
subprocess.Popen("cls", shell=True).communicate()
else:
print("\033c", end="")
# obviously you can create a function to convert your string into this
# list rather than doing it manually like I did, but that is another question :p.
views = ['#\nh\n#', '##\nhe\n##', '###\nhel\n###', '####\nhell\n####', '#####\nhello\n#####']
for view in views:
clear_screen()
print(view)
sleep(0.5)
If you are already doing print(c, end='') for each character in you string, just add flush=True to the call to print(). The sleep call will introduce enough delay so that you can see the characters print one at a time:
>>> import time
>>> s = '''###############
... Let us begin...
... ###############'''
>>> for c in s:
... print(c, end='', flush=True)
... time.sleep(0.1)

Print status update without loop iteration (python)

I have a very simple function that is just a list of data writes, but each write takes 5-10s, so the function takes about an hour to run. Since there is no loop, there is no iteration variable. What is the best way to update progress to the user?
Have you considered the logging module? You can create different kinds of handlers to, well, handle log messages. Here's a simple example, but the general idea is you can just put logging messages in your script that write to a file, a stream that prints to the console, or something else.
import datetime
import logging
import time
logger = logging.getLogger('a_name')
logger.setLevel(logging.DEBUG)
sh = logging.StreamHandler() # prints to console
logger.addHandler(sh)
with open('/tmp/test_file.txt', 'w') as f:
logger.info('beginning writing file at ' + str(datetime.datetime.now()))
time.sleep(30) # this is a proxy for doing some file writing
logger.info('the time now is' + str(datetime.datetime.now()))
...
loggering.info('file done being written')
You might want to look info formatting the log messages so you don't have to include the datetime str in an in-elegant way like I did.

Access Violation with wxPythons CallLater

I'm attempting to convert some of my code from Tkinter to wxPython. Currently I'm trying to create a function that continually loops, updating the time. However, I have run into some problems. Whenever I close the program, a window pops up, and gives me the following warning.
Access violation at address 1E058497 in module 'python26.dll'. Read of address 00000008.
This then causes my IDE (PyScripter) to freeze and crash. I think it may be trying to call the function after the program has been destroyed. This then causes it to access an unavailable location in memory, causing all sorts of fun. Any help would be appreciated.
Snippet:
def tick (self):
''' Continually updates the time. '''
TimeStr = '%I:%M %S %p'
DateStr = '%A, %B %d, %Y'
Time = time.strftime(TimeStr)
Date = time.strftime(DateStr)
self.TimeDate = Time + '\t\t' + Date
self.ST.SetLabel(self.TimeDate)
wx.CallLater(1000, self.tick)
In the Tkinter version wx.CallLater(1000, self.tick) was substituted with .after(1000, self.tick), If that helps.
Edit:
I tried it in IDLE and it seemed to work. However, no luck in PyScripter.
what you can do is:
(1)
self.scheduled_call = wx.CallLater(1000, self.tick)
during program close, cancel via, xxx.scheduled_call.??????()
I forgot the exact name of the method, please check wx docs.
OR if the above is not possible
(2) set a boolean variable in the instance, that controls the call.
if self.var: wx.CallLater(1000, self.tick)
var is True when program is running
during program close, set xxx.var to False

Categories