I know this has been asked around but everytime the example is different or more complex than what I would like to do so here goes.
First.py
value = 10 #This variable should go to the Second script
Second.py
newdata = value #This variable should come from the First script, 10
So all I want to do it pass a SINGLE variable to another python that is running independently. Please I do not want to pass all the variables from the First script to the next or call the entire second script as I have seen some examples. I am running these two scripts on the Raspberry Pi and the first script is reading some sensor data while the second scripts takes that data and further computes it. Lots of variables are used from the first script so I really don't want to pass everything, only the ones I want.
Also I would like v2.7 if that makes any difference.
Thanks
Here is my code: {The variable that I want to pass to Second.py is temp}
First.py
# External module imports
import time
import os
import datetime
import MySQLdb
os.system('sudo modprobe w1-gpio')
os.system('sudo modprobe w1-therm')
# Connect to mysql
db=MySQLdb.connect("localhost","zikmir","gforce","temp_database")
cursor=db.cursor()
while True:
# Initialization
sensor= "/sys/bus/w1/devices/28-011620ee98ee/w1_slave"
# Open the file for sensor
file = open(sensor)
# Read all of the text in the file.
text = file.read()
# Close the file now that the text has been read.
file.close()
# Split the text with new lines (\n) and select the second line.
second_line = text.split("\n")[1]
# Split the line into words, referring to the spaces, and select the 10th word (counting from 0).
temp_data = second_line.split(" ")[9]
# The first two characters are "t=", so get rid of those and convert the temperature from a string to a number.
temp = float(temp_data[2:])
# Put the decimal point in the right place and display it.
temp = temp / 1000
# Display time
t= datetime.datetime.now()
print t,temp
# Push data into mySQL
sql = "INSERT INTO time_temp VALUES(now(),%s)"
cursor.execute (sql,(temp,))
db.commit()
# Wait 5 seconds
import seven_segment
seven_segment.getdata(temp)
time.sleep(5)
Second.py
import RPi.GPIO as GPIO
import time
GPIO.setmode(GPIO.BCM)
# GPIO ports for the 7seg pins
segments = (11,2,23,8,7,10,18,25)
# 7seg_segment_pins (11,7,4,2,1,10,5,3) + 100R inline
for segment in segments:
GPIO.setup(segment, GPIO.OUT)
GPIO.output(segment, 0)
# GPIO ports for the digit 0-3 pins
digits = (22,27,17)
# 7seg_digit_pins (12,9,8) digits 0-3 respectively
for digit in digits:
GPIO.setup(digit, GPIO.OUT)
GPIO.output(digit, 1)
num = {' ':(0,0,0,0,0,0,0),
'0':(1,1,1,1,1,1,0),
'1':(0,1,1,0,0,0,0),
'2':(1,1,0,1,1,0,1),
'3':(1,1,1,1,0,0,1),
'4':(0,1,1,0,0,1,1),
'5':(1,0,1,1,0,1,1),
'6':(1,0,1,1,1,1,1),
'7':(1,1,1,0,0,0,0),
'8':(1,1,1,1,1,1,1),
'9':(1,1,1,1,0,1,1)}
try:
while True:
def getdata(temp):
n = temp
s = str(n).rjust(3)
for digit in range(3):
for loop in range(0,7):
GPIO.output(segments[loop], num[s[digit]][loop])
if (int(time.ctime()[18:19])%2 == 0) and (digit == 1):
GPIO.output(25, 1)
else:
GPIO.output(25, 0)
GPIO.output(digits[digit], 0)
time.sleep(0.001)
GPIO.output(digits[digit], 1)
finally:
GPIO.cleanup()
I have it working on a test code but not in my main code for some reason, Here is what I tried and I was successfully able to pass the data:
firsttest.py
value = 1000
def main():
print("abc")
if __name__ == "__main__":
main()
secondtest.py
from firsttest import value
recieved = value
print recieved
The out put is indeed 1000, and I only have to run the secondtest.py and the firsttest.py gets executed automatically. But when I run my original code, the first.py does execute but I'm not having any output from the second.py I don't know if this is raspberry pi related since I'm using multiple GPIO's or if this is a programming error.
Any help would be amazing. My worse solution would be to make the first.py output to a text file and have the second.py read it from there, hopefully that wont also contradict since both scripts will be trying to use it at the same time?
Use an import like this:
file1.py:
value = 1
def main():
print("execute only if called directly")
if __name__ == "__main__":
main()
and in file2.py:
from file1 import value
Make sure to have both files in one package (directory must contain an __init__.py
file). Of course you can also access the file if it is in another package.
Alternatively, you can write a get_value() function in file1.py that returns the requested value and import this function:
from file1 import get_value
value = get_value()
If temp is a variable that is updated frequently (as I suspect looking at your code), you could do either
1) write a function (eg First.read_temp()
) that reads the temperature once and then import and use this function in Second.py or
2) fetch the latest value for temp from the database (if the time delay does not matter).
Start second.py
with from first import value
. This will import only that one name into your namespace.
Keep in mind that the entire script first
will have to be run to make this work. So if you have any runnable code in your script, make sure that it is guarded be a line like if __name__ == '__main__'
.
This is going to be a bit long, so I have written an intro.
Since you are trying to get two independent processes to communicate with each other, the problem can not be solved with just imports. One process has to write the data, the other has to read it. You have a number of options available for doing this. Here are three, but keep in mind that there are other ways:
subprocess
module to communicate between them. socket
module. Of the three methods described above, the first is the most portable, but you have to start one script from the other. I can't imagine this being a huge problem for you given the code that is shown.
The second method only works on Unix-like systems, which I don't expect to be a problem on a Raspberry Pi. It allows you to run the processes completely independently: they only have to share the name of the socket between them, and you can actually guarantee that it will be the same using imports. I will not go into this method because it is probably overkill for your case.
I am not aware of any way to implement the third option using only builtin modules. You could use a library like shm , but I will not go into any detail about this method.
Before I explain how to implement items 1 and 2, I would like to propose restructuring your code a bit to make the transition process easier. I like that you have a getdata
function already planned in Second.py
. However, there are a couple more changes that I would suggest to make this process easier:
First.py :
# External module imports import time import os import datetime import MySQLdb os.system('sudo modprobe w1-gpio') os.system('sudo modprobe w1-therm') # Connect to mysql db = MySQLdb.connect("localhost","zikmir","gforce","temp_database") cursor = db.cursor() while True: # Split the text with new lines (\n) and select the second line. second_line = text.split("\n")[1] # Split the line into words, referring to the spaces, and select the 10th word (counting from 0). temp_data = second_line.split(" ")[9] # The first two characters are "t=", so get rid of those and convert the temperature from a string to a number. temp = float(temp_data[2:]) # Put the decimal point in the right place and display it. temp = temp / 1000 # Display time print datetime.datetime.now(), temp # Push data into mySQL sql = "INSERT INTO time_temp VALUES(now(),%s)" cursor.execute (sql,(temp,)) db.commit() # Wait 5 seconds seven_segment.getdata(temp) time.sleep(5)
Second.py :
import RPi.GPIO as GPIO import time GPIO.setmode(GPIO.BCM) # GPIO ports for the 7seg pins segments = (11,2,23,8,7,10,18,25) # 7seg_segment_pins (11,7,4,2,1,10,5,3) + 100R inline for segment in segments: GPIO.setup(segment, GPIO.OUT) GPIO.output(segment, 0) # GPIO ports for the digit 0-3 pins digits = (22,27,17) # 7seg_digit_pins (12,9,8) digits 0-3 respectively for digit in digits: GPIO.setup(digit, GPIO.OUT) GPIO.output(digit, 1) num = { ' ': (0,0,0,0,0,0,0), '0': (1,1,1,1,1,1,0), '1': (0,1,1,0,0,0,0), '2': (1,1,0,1,1,0,1), '3': (1,1,1,1,0,0,1), '4': (0,1,1,0,0,1,1), '5': (1,0,1,1,0,1,1), '6': (1,0,1,1,1,1,1), '7': (1,1,1,0,0,0,0), '8': (1,1,1,1,1,1,1), '9': (1,1,1,1,0,1,1), } try: while True: s = str().rjust(3) for loop in range(7): GPIO.output(segments[loop], num[][loop]) GPIO.output(, 0) time.sleep(0.001) GPIO.output(, 1) finally: GPIO.cleanup()
Most of the changes are cleanups like defining constant items outside the loop. The key additions are the calls to write_out
in First.py
and get_temp
in Second.py
.
Also notice that the functionality of First
is now within a main
function, which only gets called when __name__ == '__main__'
. This will allow you to run First.py
as a script from the command line just as you did before. When you do import First
inside Second.py
, it will not run all of the code, just define the constants that you have outside of main
.
With this method, First.py
would have to start Second.py
or vice versa. I will go with the first approach because it just seems a bit simpler. Either way, the standard output of First
will go to the standard input of Second
. You could change First.py
to read as follows:
import subprocess, sys
...
def main(proc):
...
write_out(proc, temp)
...
...
def write_out(proc, temp):
print(temp, file=proc.stdin)
proc.stdin.flush() # Necessary if you want to have real-time updates
if __name__ == '__main__':
second = subprocess.Popen([sys.executable, 'Second.py'], stdin=subprocess.PIPE, universal_newlines=True)
main(second)
Here, first kicks off Second.py
and pipes the temperature values to Second
's stdin. Here is an answer that is relevant. First.main
now has to accept a subprocess as an argument, which needs to be passed to write_out
.
Second.py
does not need any modifications in this case: just a definition of get_temp
that reads from stdin:
def get_temp():
temp = float(sys.in.readline())
Given the amount of work you have to do to make this work, you may want to consider another approach entirely. Perhaps you could just define a function that does the additional processing in Second.py
(similarly to what I did with main
in First.py
). You could then call the function in a background thread from First.py
every time you got a new temperature reading. This would make your code much simpler and easier to deal with. Assuming that your function was called process_temp
, you could do something like the following in First.py
:
import threading
...
def write_out(temp):
thread = threading.Thread(target=Second.process_temp, args=(temp,))
thread.start()
...
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.