I am having an issue where I need to access variables from one script in another. I've searched this question and I understand that we can use import to access variables in another script. The data is coming from an Arduino and is sent to a Raspberry Pi via serial and the values are continuous until the script is stopped. I have put my code into a function and I need to return the sensor data continuously.
values.py script:
import datetime
import serial
datetime.datetime.now()
ser=serial.Serial('/dev/ttyACM0',115200)
def printVal():
while True:
read_serial=ser.readline()
val= read_serial.decode()
val =val.strip()
row = [x for x in val.split(' ')]
if len(row) == 6:
#p = ('Sensor1:',row[0], 'Sensor2:',row[1], 'Sensor3:',row[2], 'Sensor4:',row[3], 'Sensor5:',row[4], 'Sensor6:',row[5])
#print (row)
#return row
sensor1= row[0]
sensor2 = row[1]
sensor3 = row[2]
sensor4 = row[3]
sensor5 = row[4]
sensor6 = row[5]
#print (sensor1, sensor2, sensor3, sensor4, sensor5, sensor6)
return (sensor1)
printVal()
second.py script:
from values import printVal
print (printVal())
I need to include the if len(row)==6 statement because the first line that prints will be three values and the other values will be out of the index.
My question is how would I access each individual array value in the second script. Would I need to print the function, I am confused on how to do this. I think the return statement is causing only one value to print and not be continuous.
You can use the json format to pass a single variable, an array, a hashmap.
For continuous transmisssion, you can read the data line by line and decode/load the data once a line is completed.
The documentation with examples :
python2 https://docs.python.org/2/library/json.html
python3 https://docs.python.org/3/library/json.html
You can return a dictionary from your printVal() function.
def printVal():
# your logic here to get sensor data
sensor_data = {'sensor1': row[0],
'sensor2': row[1],
'sensor3': row[2],
'sensor4': row[3],
'sensor5': row[4],
'sensor6': row[5]
}
return sensor_data
Then you can assign the return values to a variable in your second script like so:
from values import printVal
sensor_data = printVal()
print(sensor_data['sensor1'])
print(sensor_data['sensor6'])
Related
Currently I have set a for loop which retrieves data from the database for every row.
I need to use run a while loop, however it would not run as the for loop finishes once after it has retrieved database data. In result, this stops the rest of my While true loop to await for user response
c.execute("SELECT * FROM maincores WHERE set_status = 1")
rows = c.fetchall()
for v in rows:
# skip
while True:
#skip
I have tried using a global variable to store the database data then return the loop, all resulting in a fail.
How can I get sqlite3 database information without using for loop?
I'm not 100% on the problem, but I think you might want to use a generator so that you throttle your intake of information with your loop. So, you could do a function like:
def getDBdata():
c.execute("SELECT * FROM maincores WHERE set_status = 1")
rows = c.fetchall()
for v in rows:
yield(v) #just returns one result at a time ...
x = True
data = getDBdata()
while x is True:
do something with data
if <condition>:
next(data) #get the next row of data
else:
x = False
So, now you are controlling the data flow from your DB so that you don't exhaust your while loop as a condition of the data flow.
My apologies if I'm not answering the question your asking, but I hope this helps.
The code I am running so far is as follows
import os
import math
import statistics
def main ():
infile = open('USPopulation.txt', 'r')
values = infile.read()
infile.close()
index = 0
while index < len(values):
values(index) = int(values(index))
index += 1
print(values)
main()
The text file contains 41 rows of numbers each entered on a single line like so:
151868
153982
156393
158956
161884
165069
168088
etc.
My tasks is to create a program which shows average change in population during the time period. The year with the greatest increase in population during the time period. The year with the smallest increase in population (from the previous year) during the time period.
The code will print each of the text files entries on a single line, but upon trying to convert to int for use with the statistics package I am getting the following error:
values(index) = int(values(index))
SyntaxError: can't assign to function call
The values(index) = int(values(index)) line was taken from reading as well as resources on stack overflow.
You can change values = infile.read() to values = list(infile.read())
and it will have it ouput as a list instead of a string.
One of the things that tends to happen whenever reading a file like this is, at the end of every line there is an invisible '\n' that declares a new line within the text file, so an easy way to split it by lines and turn them into integers would be, instead of using values = list(infile.read()) you could use values = values.split('\n') which splits the based off of lines, as long as values was previously declared.
and the while loop that you have can be easily replace with a for loop, where you would use len(values) as the end.
the values(index) = int(values(index)) part is a decent way to do it in a while loop, but whenever in a for loop, you can use values[i] = int(values[i]) to turn them into integers, and then values becomes a list of integers.
How I would personally set it up would be :
import os
import math
import statistics
def main ():
infile = open('USPopulation.txt', 'r')
values = infile.read()
infile.close()
values = values.split('\n') # Splits based off of lines
for i in range(0, len(values)) : # loops the length of values and turns each part of values into integers
values[i] = int(values[i])
changes = []
# Use a for loop to get the changes between each number.
for i in range(0, len(values)-1) : # you put the -1 because there would be an indexing error if you tried to count i+1 while at len(values)
changes.append(values[i+1] - values[i]) # This will get the difference between the current and the next.
print('The max change :', max(changes), 'The minimal change :', min(changes))
#And since there is a 'change' for each element of values, meaning if you print both changes and values, you would get the same number of items.
print('A change of :', max(changes), 'Happened at', values[changes.index(max(changes))]) # changes.index(max(changes)) gets the position of the highest number in changes, and finds what population has the same index (position) as it.
print('A change of :', min(changes), 'Happened at', values[changes.index(min(changes))]) #pretty much the same as above just with minimum
# If you wanted to print the second number, you would do values[changes.index(min(changes)) + 1]
main()
If you need any clarification on anything I did in the code, just ask.
I personally would use numpy for reading a text file.
in your case I would do it like this:
import numpy as np
def main ():
infile = np.loadtxt('USPopulation.txt')
maxpop = np.argmax(infile)
minpop = np.argmin(infile)
print(f'maximum population = {maxpop} and minimum population = {minpop}')
main()
I am new to Python. I am currently working on an app that fetches data from a Data table based on the users input. So far I can't seem to find the right set of commands anywhere. Does anyone have any tips?
In more technical terms the idea is this - user inputs data, user submits, query, fetch and retrieve, prints result... any ideas?
If you are using an XLSX file, the answer posted here (openpyxl find cell or row by value) has a way to find a row based on a specific value in a cell.
If it is a CSV file, you may need to read it and create a dictionary if there is a column of unique keys, otherwise iterate through every row each time a search term is entered.
Below is a solution that should give you some ideas. NOTE I use StringIO just for the example so that I didn't have to use a file and so that the example would work out of the box. You can modify the code to read from an Excel file, Pandas DataFrame, database or any other type of storage. That choice is yours.
import csv
import StringIO
data = """date,obs1,obs2
2017-01-01,23.2,30.2
2017-02-01,14.9,13.3
"""
buffer = StringIO.StringIO()
buffer.write(data)
buffer.seek(0)
def select_action():
menu = """Would you like to: (select a number)
1) See all data?
2) See data for a specific date?
3) Exit
-->"""
action = raw_input(menu)
while action.strip() not in ['1', '2', '3']:
print "ERROR: Invalid action"
action = raw_input(menu)
def do_action(action):
if action == '1':
reader = csv.reader(buffer)
for line in reader:
print "\t".join(field for field in line)
elif action == '2':
reader = csv.DictReader(buffer)
date = raw_input("Select date: ").strip()
for line in reader:
if date == line['date']:
output = ''
for k, v in line.items():
output += ("%s: %s " % (k, v))
print output
# You could write a case for action 3, but it isn't necessary
# the way I've written the code.
print "Goodbye"
def run():
action = select_action()
do_action(action)
I am new to python and would like to have a script that looks at a feature class and compares the values in two text fields and then populates a third field with a Y or N depending on if the values are the same or not. I think I need to use an UpdateCursor with an if statement. I have tried the following but I get a syntax error when I try to run it. I am using ArcGIS 10.1 and know that the daCursor is better but I am just trying to wrap my head around cursors and thought I would try and keep it simple for now.
#import system modules
import arcpy
from arcpy import env
import os
import sys
#set environment settings
working_fc = sys.argv[1]
working_gdb = os.path.split(working_fc)[0]
#use an update cursor to populate the field BEC_UPDATED based on the result of a query
#query = ("SELECT * FROM working_fc" "WHERE [BEC_LABEL] = [BEC_V9]")
#if the query is true, then BEC_UPDATED should be popluated with "N"
#if the query is false, then BEC_UPDATED should be populated with "Y"
rows = arcpy.UpdateCursor (working_fc)
for row in rows:
if row.getValue("BEC_LABEL") == row.getValue("BEC_V9")
row.BEC_UPDATED = "N"
else
row.BEC_UPDATED = "Y"
rows.updateRow(row)
print "BEC_UPDATED field populated"
Your syntax error is caused by indentation and missing colons. Python is picky about that, so always check that when you're getting a syntax error.
rows = arcpy.UpdateCursor(working_fc)
for row in rows:
if row.getValue("BEC_LABEL") == row.getValue("BEC_V9"):
row.BEC_UPDATED = "N"
else:
row.BEC_UPDATED = "Y"
rows.updateRow(row)
Changing this to the da.UpdateCursor syntax is essentially the same, but requires you to specify the attributes you are interested in up front. It's worth practicing, because once you get into more complex scripts it will become easier :)
fieldList = ["BEC_LABEL", "BEC_V9", "BEC_UPDATED"]
with arcpy.da.UpdateCursor(working_fc, fieldList) as cursor:
for row in cursor:
if row[0] == row[1]:
row[2] = "N"
else:
row[2] = "Y"
cursor.updateRow(row)
You've forgotten the colons and indentation in your 'if' block:
rows = arcpy.UpdateCursor (working_fc)
for row in rows:
if row.getValue("BEC_LABEL") == row.getValue("BEC_V9"):
row.BEC_UPDATED = "N"
else:
row.BEC_UPDATED = "Y"
rows.updateRow(row)
print "BEC_UPDATED field populated"
I have an Excel file and I use python Win32com to operate on it.
how do I check if the last row has value in a specific column ?
when I try , the nrows is 28, not 23 (the last row have value not empty)
used = sht1.UsedRange
nrows = used.Row + used.Rows.Count - 1
UsedRange is not reliable always when you want to get last row of any specific column. You should use EndXlUp or EndXlDown function.
Check this below line:
LastRow = Sheets("Sheet1").Range("A" & Sheets("Sheet1").Rows.Count).End(xlUp).Row
Where,
A is the column to get last row.
Also, check this URL: Error in finding last used cell in VBA
As your are using python win32 com, Endxlup will not work. There's one basic thing you can do. Check the below code:
ws = wb.Worksheets('Sheet1')
rw = 2
While ws.cells(rw, 1) <> ""
rw +=1
Where,
rw is the starting row from where you want to start row count.
1 in (rw, 1) represents column. Column A represents A.
Logic behind this is while loop will run till it does not get blank cell in column A and you will get row count in variable rw
I'm currently writing an Excel wrapper, and part of it is this function returning all data from a certain offset to the last row of that column. For example, if I want everything from the 3rd row up till including the last line. This should work for your problem as well. Note where the constant is retrieved from and how all methods are stacked together to get the data and the last row.
Key functions:
def get_column_after(self, column, offset):
for item in self.ws.Range("{0}{1}:{0}{2}".format(column, offset, self.get_last_row_from_column(column))).Value:
print(item[0])
def get_last_row_from_column(self, column):
return self.ws.Range("{0}{1}".format(column, self.ws.Rows.Count)).End(win32com.client.constants.xlUp).Row
NOTE: This code is a work in progress and at the moment only supports one worksheet, one workbook per instance. I'm sure you can figure out a way to get this to work in your project though.
import string
import win32com.client
SOURCE_PATH = "C:\ExternData\somefile.xlsx"
WORKSHEET_NAME = "WS_1"
class ExcelInstance():
def __init__(self, wb=None):
self.source_path = SOURCE_PATH
try:
self.app = win32com.client.gencache.EnsureDispatch('Excel.Application')
except:
print("Application could not be opened.")
return
try:
self.open_workbook()
except:
print("Workbook could not be opened.")
return
try:
self.ws = self.wb.Worksheets(WORKSHEET_NAME)
except:
print("Worksheet not found.")
return
self.app.Visible = True
self.app.WindowState = win32com.client.constants.xlMaximized
def open_workbook(self):
"""
If it doesn't open one way, try another.
"""
try:
self.wb = self.app.Workbooks(self.source_path)
except Exception as e:
try:
self.wb = self.app.Workbooks.Open(self.source_path)
except Exception as e:
print(e)
self.wb = None
def get_column_after(self, column, offset):
for item in self.ws.Range("{0}{1}:{0}{2}".format(column, offset, self.get_last_row_from_column(column))).Value:
print(item[0])
def get_last_row_from_column(self, column):
return self.ws.Range("{0}{1}".format(column, self.ws.Rows.Count)).End(win32com.client.constants.xlUp).Row
def main():
f = ExcelInstance()
f.get_column_after("A", 3)
if __name__ == "__main__":
main()
xlUp is nothing short of a pre-defined constant.
So the most simple way is to type the code in the direct window of the VBE
? xlUp
you will see the following result.
-4162
add the line to your python code
xlUp = -4162
Done!
Replace .End(xlUp).Row with .End(3).Row.
i use this stupid way to do . not sure have problem or not. so far work for myself
def find_lastrow_oncolumn(worksht, colno):
used = worksht.UsedRange
nrows = used.Row + used.Rows.Count - 1
lastrow_havevalue = 0
for k in range(nrows):
if worksht.Cells(nrows-k, colno).Value is not None:
print worksht.Cells(nrows-k, colno).Value, nrows-k , k
lastrow_havevalue = nrows-k
break
return lastrow_havevalue