I have a class where all of our data is in, here I open a file by:
carIn= open("dataIn.txt","w")
carOut= open("dataUit.txt","w")
In another class I have a loop for the main program. I closed my file in the loop but it won't open again. If I close it outside the loop, the entire program crashes. This is my code:
while startScreen.getstopt() == False:
startScreen.start()
print("screen start")
screen = Screen(wereld.getIntersection())
startSimulatiion()
print("Simulatiion start:")
for x in Files.listIn:
Files.carIn.write(str(x) + "\n")
for x in Files.listOut:
Files.carOut.write(str(x) +"\n")
result= Resultaten()
Files.calculatedRatio= result.calculateRatio()
print(Files.calculatedRatio)
if screen.startScreen == True:
Files.carIn.write("\n")
Files.carIn.write("\n")
Files.carIn.write("\n")
Files.carOut.write("\n")
Files.carOut.write("\n")
Files.carOut.write("\n")
Files.carIn.close()
Files.carOut.close()
In my opinion, you shouldn't be holding open objects in class / instance variables to pass around. This will become messy and it's easy to forget to close explicitly.
Instead, I would hold the filenames in variables and pass them into functions which open and close files via with statements.
Here is an example:
Files.carIn = 'dataIn.txt'
Files.carOut = 'dataUit.txt'
with open(Files.carIn, 'w') as file_in, open(Files.carOut, 'w') as file_out:
while startScreen.getstopt() == False:
# do things with file_in & file_out
Related
apologies if this question has been asked somewhere before, but I couldn't find a solution / info i was looking for.
So: I am running a raspberry pi 0W with a python script reading 4 temperature sensors monitoring some stuff at home. I am reading these sensors every 2 minutes and write the output into a CSV (for the time being sufficient for me). When I ssh my PI and run my script in TMUX, I realised that when calling my "Sensordata.csv" it only updates, once I close the script in my TMUX session. Ideally I want my "Sensordata.CSV" file update after each polling cycle.
I believe its not the code, as my code opens, writes and closes the file while running in the shell normally. Hope someone can help me out =)
import time
import csv
from datetime import datetime
def get_temp(dev_file):
f = open(dev_file,"r")
contents = f.readlines()
f.close()
index = contents[-1].find("t=")
if index != -1 :
temperature = contents[-1][index+2:]
cels =float(temperature)/1000
return cels
time_for_csv=time.asctime( time.localtime(time.time()))
f=open("Sensordata.csv", "a")
c=csv.writer(f)
if __name__ =="__main__":
while True:
dateTimeObj = datetime.now()
timestampStr = dateTimeObj.strftime("%d-%b-%Y (%H:%M:%S.%f)")
temp = get_temp("//sys/bus/w1/devices/28-0301a2799ec4/w1_slave")
temp2 = get_temp("//sys/bus/w1/devices/28-0301a2790081/w1_slave")
temp3 = get_temp("//sys/bus/w1/devices/28-012020be268d/w1_slave")
tempout = get_temp("//sys/bus/w1/devices/28-00000b0f6540/w1_slave")
print('Current Timestamp : ', timestampStr, "28-00000b0f6540 - Outside Sensor", tempout)
print('Current Timestamp : ', timestampStr, "28-0301a2799ec4 - Floorheating out", temp)
print('Current Timestamp : ', timestampStr, "28-0301a2790081 - Floorheating in", temp2)
print('Current Timestamp : ', timestampStr, "28-012020be268d - Room Sensor", temp3)
f = open("Sensordata.csv", "a")
c = csv.writer(f)
c.writerow([timestampStr, temp, temp2, temp3, tempout])
f.close()
time.sleep(120)
I don't think that Tmux is part of the issue.
Try removing these 3 lines of code in your script:
time_for_csv=time.asctime( time.localtime(time.time()))
f=open("Sensordata.csv", "a")
c=csv.writer(f)
time_for_csv is unused.
When opening a file for writing or appending, a safer way is to use the following:
with open("Sensordata.csv", "a") as f:
c=csv.writer(f)
c.writerow([timestampStr, temp, temp2, temp3, tempout])
The file object will always be closed even if an exception is raised. You do not have to close it explicitly. See With statement in Python
I am guessing that your opening a file object in the middle of the script leaves a file open, and then you re-define f after the if __name__ == "__main__. Leaving file objects open can have unpredictable results like the one you're experiencing.
i was programming a notepad with tkinter, but when i tried to define "createNewFile" that create before creating the new file, ask you to save, but it give me an error. Expected an indented block (, line 32). Here's the code:
def createNewFile():
if len(textArea.get("1.0", END+"-1c")) > 0:
if messagebox.askyesno("Save?", "Do you wish to save the file?"):
saveFile()
else:
textArea.delete("1.0",END)
def saveFile():
file = filedialog.asksaveasfile(mode='w',defaultextension=".txt", filetypes=(("Text File",".txt"), ("All Files","*.*"),("HTML Files",".html .htm"),("CSS Files",".css")))
if file != None:
data = self.textArea.get('1.0', END+'-1c')
file.write(data)
file.close()
The line that follows the second if statement in the createNewFile() function (i.e., saveFile()) needs to be indented.
def createNewFile():
if len(textArea.get("1.0", END+"-1c")) > 0:
if messagebox.askyesno("Save?", "Do you wish to save the file?"):
saveFile()
else:
textArea.delete("1.0",END)
I'm a JS dev trying to learn a bit of Python while working on a Raspberry-Pi3 project that reads data from a Bluetooth temperature sensor.
I need to write the data to my file.txt every 10 seconds, how could I do that please? I found similar topic here (Run certain code every n seconds ), but I don't know how to make it work in my current scenario.
#!/usr/bin/env python3
import argparse
import re
import logging
import sys
import time
from btlewrap import available_backends, BluepyBackend, GatttoolBackend, PygattBackend
from mitemp_bt.mitemp_bt_poller import MiTempBtPoller, \
MI_TEMPERATURE, MI_HUMIDITY, MI_BATTERY
def valid_mitemp_mac(mac, pat=re.compile(r"4C:65:A8:[0-9A-F]{2}:[0-9A-F]{2}:[0-9A-F]{2}")):
"""Check for valid mac adresses."""
if not pat.match(mac.upper()):
raise argparse.ArgumentTypeError('The MAC address "{}" seems to be in the wrong format'.format(mac))
return mac
def poll(args):
"""Poll data from the sensor."""
backend = _get_backend(args)
poller = MiTempBtPoller(args.mac, backend)
line1 = "Temperature: {}".format(poller.parameter_value(MI_TEMPERATURE))
line2 = "Humidity: {}".format(poller.parameter_value(MI_HUMIDITY))
print("Getting data from Mi Temperature and Humidity Sensor")
print("FW: {}".format(poller.firmware_version()))
print("Name: {}".format(poller.name()))
print("Battery: {}".format(poller.parameter_value(MI_BATTERY)))
print(line1)
print(line2)
f = open('file.txt', 'w')
f.write("%s \n %s \n" % (line1, line2))
f.close()
def _get_backend(args):
"""Extract the backend class from the command line arguments."""
if args.backend == 'gatttool':
backend = GatttoolBackend
elif args.backend == 'bluepy':
backend = BluepyBackend
elif args.backend == 'pygatt':
backend = PygattBackend
else:
raise Exception('unknown backend: {}'.format(args.backend))
return backend
def list_backends(_):
"""List all available backends."""
backends = [b.__name__ for b in available_backends()]
print('\n'.join(backends))
def main():
parser = argparse.ArgumentParser()
parser.add_argument('--backend', choices=['gatttool', 'bluepy', 'pygatt'], default='gatttool')
parser.add_argument('-v', '--verbose', action='store_const', const=True)
subparsers = parser.add_subparsers(help='sub-command help', )
parser_poll = subparsers.add_parser('poll', help='poll data from a sensor')
parser_poll.add_argument('mac', type=valid_mitemp_mac)
parser_poll.set_defaults(func=poll)
parser_scan = subparsers.add_parser('backends', help='list the available backends')
parser_scan.set_defaults(func=list_backends)
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.DEBUG)
if not hasattr(args, "func"):
parser.print_help()
sys.exit(0)
args.func(args)
if __name__ == '__main__':
main()
You can use the time module to pause the program for 10 seconds on each iteration;
from time import sleep
def func(n):
print(n+1)
for i in range(5):
func(i)
sleep(10)
>1
>2
>3
>4
>5
# (every 10 seconds)
However this will block the rest of the program running, although a simple multi-threading script to call the writing function would suffice.
And in relation to the code you are using, insert the sleep call within the poll function and wrap what you have there. If you want to loop the program 10 times then;
def poll(args):
"""Poll data from the sensor."""
for _ in range(10):
# code things
f = open('file.txt', 'a') # << Use append here or you will keep overwriting file contents
f.write('hello')
f.close()
sleep(10)
Or if you want it to run forever until you KeyboardInterrupt or exit somehow:
def poll(args):
"""Poll data from the sensor."""
while True:
# code things
f = open('file.txt', 'a') # << Use append here or you will keep overwriting file contents
f.write('hello')
f.close()
sleep(10)
you need some kind of loop that polls your sensor - I do not see one glancing over your code. You got while and for loops in JS as well - look them up in http://docs.python.org/3/tutorial if you are unsure about the syntax.
store the time you wrote to a variable , sleep a bit poll the next value, check if 10s passed, write if, else not. (or simply sleep 10s between polls if you do not want intermediate values printed
Readup about loops:
for statement
looping techniques
import time
def poll():
return time.time(), 42
last_write = None # when did we record to file last?
# loop for as long as you want - while True would loop endlessly
for _ in range(7):
t,c = poll() # call poll() to get time and temperature from mocked data reader
# check if enough time has passed
if last_write is None or (t-last_write) > 2: # check if new reading needed
with open("t.txt","a") as f:
f.write(f"{t} {c}\n")
last_write=t
print("in file ", t,c)
else:
print("just output ", t,c)
time.sleep(0.7) # sleep some
Output:
in file 1552978725.5224085 42 # ...25.5
just output 1552978726.2232893 42 # ...26.2 - not 2s passed
just output 1552978726.9241226 42 # ...26.9 - not 2s passed
in file 1552978727.6249442 42 # ...27.6 - 2.1s passed
just output 1552978728.3259027 42 # ...28.3 - not 2s passed
just output 1552978729.0267787 42 # ...29.0 - not 2s passed
in file 1552978729.7275977 42 # ...29.7 - 2.1s passed
More remarks:
use with open(filename,mode) as f: and scope the file opeations below it - it will autoclose your file after scope and handle exceptions by closing the filehandle as well.
Using mode "w" will truncate the file before writing to it - you might want to use append instead: reading and writing files
I'm trying to get if statements to run and it seems only the 1st one will run the others are just skipped. I have tried adding else and dummy action and still skips over the other. I have been playing with the for a couple days and can't seem to get it to check all the if statements.
#!/usr/bin/env python
#version 1.1 Beta
import maidenhead as mh
from math import radians, sin, cos, acos
import re
import telnetlib
import time
import sys
HOST = "xxxxx" #set your cluster host-name here
PORT = 7300 #cluster port
user = "xxxx" #cluster user
mygrid = "fn10"
sys.stdout.write('\33]0;KM4OUS Cluster Connector\a')
sys.stdout.flush()
tn = telnetlib.Telnet(HOST,PORT)
tn.read_until(b"login: ")
tn.write(user.encode('ascii') + b"\n")
count = 0
timer = 0
tsb = "y"
fsb = "y"
tcw = "y"
fcw = "y"
print("Welcome to the KM4OUS Cluster Connector")
while (count < 1):
fw = open("cluster.csv", "w")
push = tn.read_very_eager()
fw.write(push)
fw.close()
f = open('cluster.csv','r')
#
if fcw == "y":
regexd = re.compile(r'(DX de .+\s70[2-9].+Z\s\w\w\w\w)')
for z in f:
ftcw = regexd.findall(z)
for ftc in ftcw:
ftc = re.sub('\'|\,|\(|\)','', str(ftc))
print(ftc)," \n40M CW DIGI"
if tsb == "y":
regexa = re.compile(r'(DX de .+\s142[2-9].+Z\s\w\w\w\w)|(DX de .+\s143[0-5].+Z\s\w\w\w\w)')
for x in f:
twssb = regexa.findall(x)
for tws in twssb:
tws = re.sub('\'|\,|\(|\)|\"','', str(tws))
print(tws),"\n20M SSB"
if tcw == "y":
regexb = re.compile(r'(DX de .+\s140[2-9].Z\s\w\w\w\w)')
for xc in f:
twcw = regexb.findall(xc)
for twc in twcw:
twc = re.sub('\'|\,|\(|\)|\"','', str(twc))
print(twc)," \n20M CW DIGI"
if fsb == "y":
regexc = re.compile(r'(DX de .+\s717[8-9].Z\s\w\w\w\w)|(DX de .+\s72[0-9].Z\s\w\w\w\w)|(DX de .+\s718.Z\s\w\w\w\w)')
for y in f:
forty = regexc.findall(y)
for fts in forty:
fts = re.sub('\'|\,|\(|\|\")','', str(fts))
print(fts)," \n40M SSB"
f.close()
time.sleep(5)
if timer == 30:
print ("\n" + time.ctime() + "\nKM4OUS CLuster Connector\n")
#cw.close()
count = 0
timer = timer+1
if anyone has a simple solution I would like to hear it. This seems like something that should be simple but it's not working as expected. I looked up all the info on if elif and else and can't find anything that's close to this.
The issue with your code is not with the if statements, but with the for loop you have over the file f. That kind of loop will consume the contents of the file the first time you run it. If you try looping over the file again in one of the later if blocks, there will be nothing to loop over.
There are a few ways you can fix the issue.
One is to open the file in the if blocks, rather than once at the top of the while. This way, each of the inner loops gets its own file to iterate over:
# don't open f up here
if fcw == "y":
regexd = re.compile(r'(DX de .+\s70[2-9].+Z\s\w\w\w\w)')
with open('cluster.csv','r') as f:
for z in f:
...
if tsb == "y":
regexa = re.compile(r'(DX de .+\s142[2-9].+Z\s\w\w\w\w)|(DX de .+\s143[0-5].+Z\s\w\w\w\w)')
for x in f:
twssb = regexa.findall(x)
for tws in twssb:
...
if tcw == "y":
regexb = re.compile(r'(DX de .+\s140[2-9].Z\s\w\w\w\w)')
with open('cluster.csv','r') as f:
for xc in f:
...
In that code I'm using a with statement in each place I open f, as that will close the file automatically when the block ends. I would recommend using with for your other files as well.
Another approach would be to rewind the file object to the start before you loop over it. You can do this with f.seek(0). I'd put one before each of your loops, as it doesn't hurt to seek to the start of the file if you're already there. Note that the ability to seek forwards and backwards is an idiosyncratic feature of files in Python. Most iterators cannot do that. They are one-shot and once you've consumed them, there's no way to go back.
A final option is to read the lines from your file into a list or other data structure and iterate over that instead of over the file. You can either do f.readlines() or just list(f) to get a list of lines, and you can iterate over the list as many times as you want. Or, since you're writing the contents of the file based on the push variable at the top of the while loop, maybe you can skip the file all together and just use something like push.splitlines().
Put print statements under each if statement and you will see that they are in fact running.
The problem is that once you iterate over the file object once, it reaches the end. The next time you iterate, it's already at the end and does nothing.
You either need to reset the file location, or close the file and read it again each time. Read the I/O section of the Python tutorial. https://docs.python.org/3/tutorial/inputoutput.html
I have a python script that calls a system program and reads the output from a file out.txt, acts on that output, and loops. However, it doesn't work, and a close investigation showed that the python script just opens out.txt once and then keeps on reading from that old copy. How can I make the python script reread the file on each iteration? I saw a similar question here on SO but it was about a python script running alongside a program, not calling it, and the solution doesn't work. I tried closing the file before looping back but it didn't do anything.
EDIT:
I already tried closing and opening, it didn't work. Here's the code:
import subprocess, os, sys
filename = sys.argv[1]
file = open(filename,'r')
foo = open('foo','w')
foo.write(file.read().rstrip())
foo = open('foo','a')
crap = open(os.devnull,'wb')
numSolutions = 0
while True:
subprocess.call(["minisat", "foo", "out"], stdout=crap,stderr=crap)
out = open('out','r')
if out.readline().rstrip() == "SAT":
numSolutions += 1
clause = out.readline().rstrip()
clause = clause.split(" ")
print clause
clause = map(int,clause)
clause = map(lambda x: -x,clause)
output = ' '.join(map(lambda x: str(x),clause))
print output
foo.write('\n'+output)
out.close()
else:
break
print "There are ", numSolutions, " solutions."
You need to flush foo so that the external program can see its latest changes. When you write to a file, the data is buffered in the local process and sent to the system in larger blocks. This is done because updating the system file is relatively expensive. In your case, you need to force a flush of the data so that minisat can see it.
foo.write('\n'+output)
foo.flush()
I rewrote it to hopefully be a bit easier to understand:
import os
from shutil import copyfile
import subprocess
import sys
TEMP_CNF = "tmp.in"
TEMP_SOL = "tmp.out"
NULL = open(os.devnull, "wb")
def all_solutions(cnf_fname):
"""
Given a file containing a set of constraints,
generate all possible solutions.
"""
# make a copy of original input file
copyfile(cnf_fname, TEMP_CNF)
while True:
# run minisat to solve the constraint problem
subprocess.call(["minisat", TEMP_CNF, TEMP_SOL], stdout=NULL,stderr=NULL)
# look at the result
with open(TEMP_SOL) as result:
line = next(result)
if line.startswith("SAT"):
# Success - return solution
line = next(result)
solution = [int(i) for i in line.split()]
yield solution
else:
# Failure - no more solutions possible
break
# disqualify found solution
with open(TEMP_CNF, "a") as constraints:
new_constraint = " ".join(str(-i) for i in sol)
constraints.write("\n")
constraints.write(new_constraint)
def main(cnf_fname):
"""
Given a file containing a set of constraints,
count the possible solutions.
"""
count = sum(1 for i in all_solutions(cnf_fname))
print("There are {} solutions.".format(count))
if __name__=="__main__":
if len(sys.argv) == 2:
main(sys.argv[1])
else:
print("Usage: {} cnf.in".format(sys.argv[0]))
You take your file_var and end the loop with file_var.close().
for ... :
ga_file = open(out.txt, 'r')
... do stuff
ga_file.close()
Demo of an implementation below (as simple as possible, this is all of the Jython code needed)...
__author__ = ''
import time
var = 'false'
while var == 'false':
out = open('out.txt', 'r')
content = out.read()
time.sleep(3)
print content
out.close()
generates this output:
2015-01-09, 'stuff added'
2015-01-09, 'stuff added' # <-- this is when i just saved my update
2015-01-10, 'stuff added again :)' # <-- my new output from file reads
I strongly recommend reading the error messages. They hold quite a lot of information.
I think the full file name should be written for debug purposes.