简体   繁体   中英

Passing a single variable from one python program to another program

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__' .

INTRO

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:

  1. Have one process start the other and use the subprocess module to communicate between them.
  2. Use Unix Domain Sockets , which are like regular sockets, but can be accessed via a named file on a Linux (or other Unix implementation) machine. This would use the socket module.
  3. Use a shared memory implementation to just write the value in a shared piece of memory. As far as I know there is no built-in module for doing this with processes that are completely independent of each other.

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.

Code

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 .

Subprocess Method

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())

Conclusion

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM