I was wondering if it was possible to perform an action at any given point in a basic python script, so say when it is close. I have the following code to find prime numbers (Just for fun)
number = 1
primelist = []
nonprime = []
while number < 1000:
number += 1
for i in range(number):
if i != 1 and i != number and i !=0:
if number%i == 0:
nonprime.append(number)
else:
primelist.append(number)
nonprimes = open("nonprimes.txt", "w")
for nonprime in set(primelist) & set(nonprime):
nonprimes.write(str(nonprime) + ", ")
nonprimes.close()
So basically i wanted to run the last part as the script is stopped. If this isn't possible is there a way where say i press "space" while the program is running and then it saves the list?
Cheers in advance :)
EDIT:
I've modified the code to include the atexit module as suggested, but it doesn't appear to be working. Here it is:
import time, atexit
class primes():
def __init__(self):
self.work(1)
def work(self, number):
number = 1
self.primelist = []
self.nonprime = []
while number < 20:
time.sleep(0.1)
print "Done"
number += 1
for i in range(number):
if i != 1 and i != number and i !=0:
if number%i == 0:
self.nonprime.append(number)
else:
self.primelist.append(number)
nonprimes = open("nonprimes.txt", "w")
for nonprime in set(self.primelist) & set(self.nonprime):
nonprimes.write(str(nonprime) + ", ")
nonprimes.close()
def exiting(self, primelist, nonprimelist):
primelist = self.primelist
nonprimelist = self.nonprime
nonprimes = open("nonprimes.txt", "w")
for nonprime in set(self.primelist) & set(self.nonprime):
nonprimes.write(str(nonprime) + ", ")
nonprimes.close()
atexit.register(exiting)
if __name__ == "__main__":
primes()
While I'm pretty certain the file object does cleanup and flushes the stuff to file when it is reclaimed. The best way to go about this is to use a with statement.
with open("nonprimes.txt", "w") as nonprimes:
for nonprime in set(primelist) & set(nonprime):
nonprimes.write(str(nonprime) + ", ")
The boiler plate code of closing the file and such is performed automatically when the statement ends.
Python has an atexit module that allows you to register code you want executed when a script exits:
import atexit, sys
def doSomethingAtExit():
print "Doing something on exit"
atexit.register(doSomethingAtExit)
if __name__ == "__main__":
sys.exit(1)
print "This won't get called"
Related
I need to make two checks in log files and display the result. Separately methods work correctly, but when I run all code method hit_unique_check always return "PASS: All hits are unique.". For two of three .log files this result is incorrect.
import os
class ReadFiles:
def __init__(self):
self.current_file = ""
self.shoot_from = "Shoot from"
self.hit_player = "Hit player"
def equally_check(self):
shoot_from_list = []
hit_player_list = []
for line in self.current_file:
if self.shoot_from in line:
shoot_from_list.append(line)
elif self.hit_player in line:
hit_player_list.append(line)
if len(shoot_from_list) == len(hit_player_list):
print(" PASS: Shoots and hits are equal.\n")
else:
print(" FAIL: Shoots and hits are NOT equal.\n")
def hit_unique_check(self):
unique_hit_list = []
duplicates = []
for line in self.current_file:
if self.hit_player in line:
unique_hit_list.append(line)
else:
continue
for i in unique_hit_list:
if unique_hit_list.count(i) > 1:
duplicates.append(i)
print(i)
else:
continue
if len(duplicates) < 1:
print(" PASS: All hits are unique.\n")
else:
print(" FAIL: This hits are duplicated.\n")
def run(self):
for file in os.listdir():
if file.endswith(".log"):
print(f"Log file - {file}")
self.current_file = open(f"{file}", 'rt')
print(self.current_file.readlines, f"")
self.equally_check()
self.hit_unique_check()
self.current_file.close()
if __name__ == "__main__":
run = ReadFiles()
run.run()
I run my python code, but result always the same: "PASS: All hits are unique.". For some files it must be "FAIL: This hits are duplicated.". I'm not sure that problem in the method hit_unique_check, and have no idea what to do.
Can you explain me, how I can make this method working correctly not only separately?
Consider this organization. Each function has one task, to evaluate and return its result. It's up to the caller to decide what to do with the result. Also note that I'm using counters instead of lists, since you don't really care what the lists contain. Also note the use of defaultdict, to avoid having to do repeated searches of your hit list.
import os
from collections import defaultdict
class ReadFiles:
def __init__(self):
self.shoot_from = "Shoot from"
self.hit_player = "Hit player"
def equally_check(self, lines):
shoot_from = 0
hit_player = 0
for line in lines:
if self.shoot_from in line:
shoot_from += 1
elif self.hit_player in line:
hit_player += 1
return shoot_from == hit_player
def hit_unique_check(self, lines):
unique_hit_list = defaultdict(int)
for line in lines:
if self.hit_player in line:
unique_hit_list[line] += 1
duplicates = 0
for k,v in unique_hit_list.items()
if v > 1:
duplicates += 1
print(k)
return not duplicates
def run(self):
for filename in os.listdir():
if filename.endswith(".log"):
print(f"Log file - {filename}")
lines = open(filename, 'rt').readlines()
print(lines)
if self.equally_check(lines):
print(" PASS: Shoots and hits are equal.\n")
else:
print(" FAIL: Shoots and hits are NOT equal.\n")
if self.hit_unique_check(lines):
print(" PASS: All hits are unique.\n")
else:
print(" FAIL: This hits are duplicated.\n")
if __name__ == "__main__":
run = ReadFiles()
run.run()
You could even replace the loop in hit_unique_check with a counter:
from collections import Counter
...
def hit_unique_check(self,lines):
unique_hit_list = Counter(lines)
for k,v in unique_hit_list,items():
...
Please help me. I wanted the counter num variable to add everytime the function is ran. But its not working, please tell me why I did wrong. If I use return num then the code is ending which I dont want, but n =+1 is not working, please help. Thanks a lot.
def prompt():
num = 1
print(num)
question = input("Do you want to add a file(y,n): ")
if question == "y":
file = input("Which File?: ")
nukefile.append(file)
st_frm = input("Start frame: ")
start_frame.append(st_frm)
en_frm = input("End Frame: ")
end_frame.append(en_frm)
#return num + 1
num =+1
print(num)
nukew = str("start /wait Nuke11.1.exe -x -"+st_frm+"-"+en_frm+" "+file)
nukewrite.append(nukew)
que = (str(num)+". "+file+"--"+st_frm+","+en_frm)
for_artist.append(que)
for x in for_artist:
print(x)
prompt()
return num
elif question == "n":
print(nukewrite)
f = open(batchfile, "a")
for shotsa in nukewrite:
f.write('\n'+shotsa+'\n')
print("Following files will render:")
for shotsb in nukefile:
print(shotsb)
f.close()
else:
print("Invalid entry")
prompt()
If you want to count how many times the function runs and keep it recursive, you'll need to define prompt.num outside of prompt. You can define it under the function or use a decorator and define it above.
def prompt():
prompt.num += 1
your code
prompt.num = 0
I'm currently writing 2 programs in python that must play a number game against each other. One program picks a number between 1 and 100. Then the other attempts to guess what that number is. Each time the guesser gives it's guess, the chooser then replies with 'too big', 'too small', or 'you got it'. According to what the reply is the guesser adjusts its next guess accordingly.
Here's my code for the program that chooses:
import random
from guesser import g
guessCount = 0
number = random.randint(1, 100)
print("I'm thinking of a number between 1 and 100.")
outfile = open ('response.txt', 'w')
guess = 50
print (guess)
if guess < number:
print('Your guess is too low.')
switch = '1'
outfile.write (switch + '\n')
elif guess > number:
print('Your guess is too high.')
switch = '2'
outfile.write (switch + '\n')
else:
print('Correct, You guessed the number in', guessCount, 'guesses.')
switch = '3'
outfile.write (switch + '\n')
while guessCount < 8:
guess = g
print (guess)
guessCount += 1
if guess < number:
print('Your guess is too low.')
switch = '1'
outfile.write (switch + '\n')
elif guess > number:
print('Your guess is too high.')
switch = '2'
outfile.write (switch + '\n')
else:
print('Correct, You guessed the number in', guessCount, 'guesses.')
switch = '3'
outfile.write (switch + '\n')
break
outfile.close()
print('The number was',number)
And here's the code for the program that gives the guesses:
low = 1
high = 100
guess = 0
guessCounter = 0
infile = open ('response.txt', 'r')
switch = int (infile.readline())
def g (switch):
while switch != 3 and guessCounter < 8:
guess = (low+high)//2
guessCounter += 1
if switch == 1:
high = guess
elif switch == 2:
low = guess + 1
return guess
My main question is how to get the 2 programs to interact with eachother. I'm currently trying to use a method of having them communicate through a text file called response, but surely there's an easier way?
The main problem I'm having it seems is that when chooser tries to get the variable g from guesser it can't because there's no response currently in response.txt meaning switch = int ('')
Traceback (most recent call last): File
"C:\Users\Jash\Downloads\guesser.py", line 8, in
switch = int (infile.readline()) ValueError: invalid literal for int() with base 10: ''
And yes, they must be 2 separate programs. And it must be done in python.
It would be a lot easier to put both players in the same program.
If you really want to use 2, though, you can run them like this on unix or linux:
echo "" > somefile
tail -f somefile | program1 | program2 >> somefile
This will effectively pipe each program's output into the other's input. Of course anything you want to see should be printed to standard error.
You can open the child scripts from your main script like this:
from subprocess import Popen, PIPE
prog = Popen("child.py", shell=True, stdin=PIPE, stdout=PIPE)
prog.stdin.write("Message to child.py maybe from another child?\n")
print prog.stdout.read() #Response from child
prog.wait() # Wait for script to finish run next script
as mentioned by Matt Timmermans:
if it is not absolutely neccessary, put the whole logic into one program:
import random
def createNum():
return random.randint(1,101)
lastGuess = 0
randMin, randMax = 1, 101
def guessNum(sigmoidAdjustmentInt):
# sigmoidAdjustmentInt represents a number which is negative, equal to zero or positiv; e.g. [-1 / 0 / +1]
# 0 == no information about to big or to small number
# -1 == number has to be smaller this time
# 1 == number has to be bigger this time
# guess somehow; e.g. with random again
if sigmoidAdjustmentInt < 0:
randMax = lastGuess-1
elif 0 < sigmoidAdjustmentInt:
randMin = lastGuess+1
return random.randint(randMin,randMax)
def main():
secretNumber = createNum()
guessedCorrectly = False
triesCounter = 0
sigmoidAdjustmentInt = 0 # set here for the first call
while not guessedCorrectly:
triesCounter = 0
if guessNum(sigmoidAdjustmentInt) == secretNumber:
guessedCorrectly = True
break
# print here if too high or low
print("needed guesses: "+ triesCounter)
# do something else
please note that the random.randint(...)-calls of createNum and guessNum are only placeholders for your preferred implementations of it.
see also: random.randint
as for your question how to execute multiple scripts.
say you have 3 files:
a.py
b.py
c.py
you start a.py, it does something, calls b.py and after that calls c.py with the result.
you can do it this way:
# in a.py
import subprocess
args = ( # rebuild the commandline call of the file here; the following stands for the comandline command: python b.py
"python", # every whitespace in the cmd-command is a comma in this args-tuple
"b.py"
)
popen = subprocess.Popen(args, stdout=subprocess.PIPE)
popen.wait()
resultsOfB, errorsOfB = popen.communicate()
del popen
args = ( # this represents: python c.py someStringValueContainedInResultFromB
"python",
"c.py",
resultOfB # lets just say this var contains a string => if not convert it to one
)
popen = subprocess.Popen(args, stdout=subprocess.PIPE)
popen.wait()
resultsOfC, errorsOfC = popen.communicate()
# do something with the results of c.py
again: if you write all three of the files, consider to put them together into one. this method is good if you have to call third party software or something like that (e.g.:)
Create a third, referee program. Take two arguments - the names of the picker and the guesser programs. Have the referee program open read/write pipes to the two programs, and using either the subprocess or the pexpect module.
I'm making a dart score keeper but it just keeps going round and round. I just need some help as to why this is.
The code:
import time
import sys
from sys import argv
script, name1, name2 = argv
def dartscore():
print "Play from 501 or 301?"
threeorfive = int(raw_input())
if (threeorfive == 501):
def playerone():
startnum1 = threeorfive
while (startnum1 > 0):
print "Ready ", name1,"?"
print "Please enter your score."
minusnum1 = int(raw_input())
startnum1 = startnum1 - minusnum1
playertwo()
if (startnum1 == 0):
print "Well done! You win!"
elif (startnum1 < 0):
print "Sorry but you have entered a wrong score"
playertwo()
def playertwo():
startnum2 = threeorfive
print "Ready ", name2,"?"
print "Please enter your score."
minusnum2 = int(raw_input())
startnum2 = startnum2 - minusnum2
if (startnum2 == 0):
print "Well done! You win!"
print "Unlucky ", name1,". Well played though."
sys.exit()
if (startnum2 < 0):
print "Sorry but you have entered an incorrect score. Please try again"
startnum2 += minusnum2
playerone()
playerone()
dartscore()
Now the two functions playerone() and playertwo() are different because I was trying something with the playerone() function to see if that solved my problem.
Well you have a while(startnum1 > 0):. It seems like startnum1is always bigger then 0. The only way to exit your loop is player 2 has a startnum2 on 0.
Your problem is:
threeorfive = 501
Throughout the entire game, and you begin each of your functions with
startnum = threeorfive
Which means the game 'resets' after both player takes a turn.
A possible fix would be to add global variables:
cumulative1 = 0
cumulative2 = 0
then update cumulative in each iteration:
cumulative1 += minusnum1
cumulative2 += minusnum2
and change your while loop to:
while(threeorfive - cumulative1 > 0)
while(threeorfive - cumulative2 > 0)
I am trying to make an on/off switch for my program:
(see after the ### for what I'm talking about)
while 1:
str = raw_input("insert your word: ")
n = input("insert your scalar: ")
def string_times(str, n):
return n * str
print string_times(str, n)
###
def switch(on,off):
raw_input("On or off? ")
if switch == "on":
continue
if switch == "off":
break
switch(on,off)
I get a continue not in loop error. Basically, I want to create an on or off switch after the program runs once. What do I fix?
You cannot use break and continue in a nested function. Use the return value of the function instead:
def switch():
resp = raw_input("On or off? ")
return resp == "on":
while True:
# other code
if not switch():
break
Note that there is little point in defining your functions in the loop. Define them before the loop, as creating the function object takes some performance (albeit a small amount).
The switch() function needs no arguments (you didn't use them at all), and the continue is also not needed. If you didn't break out of the loop, it'll just continue from the top when you reach the end.
You only need continue if you want the loop to start at the top again skipping the rest of the code in the loop:
count = 0
while True:
count += 1
print count
if loop % 2 == 0:
continue
print 'We did not continue and came here instead.'
if count >= 3:
break
print 'We did not break out of the loop.'