将一个变量从一个python程序传递到另一个程序

时间:2017-04-26 10:23:20

标签: python python-2.7 raspberry-pi gpio

我知道这已被问到,但每次这个例子都不同于我想做的事情或者比我想做的更复杂。所以这里就是这样。

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

所以我想做的就是将一个SINGLE变量传递给另一个独立运行的python。我不想将所有变量从First脚本传递到下一个脚本或调用整个第二个脚本,因为我已经看到了一些示例。我在Raspberry Pi上运行这两个脚本,第一个脚本正在读取一些传感器数据,而第二个脚本获取该数据并进一步计算它。从第一个脚本中使用了很多变量,所以我真的不想传递所有内容,只传递我想要的内容。

如果这有任何区别,我也想要v2.7。

由于

这是我的代码:{我要传递给Second.py的变量是临时}

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

我有一个测试代码但由于某些原因没有在我的主代码中工作,这是我尝试过的,我成功地传递了数据:

firsttest.py

value = 1000

def main():
    print("abc")
if __name__ == "__main__":
    main()

secondtest.py

from firsttest import value
recieved = value
print recieved

输出确实是1000,我只需运行secondtest.py并自动执行firsttest.py。但是当我运行我的原始代码时,first.py会执行,但我没有从second.py获得任何输出 我不知道这是否与树莓有关,因为我使用了多个GPIO,或者这是编程错误。

任何帮助都会很棒。我更糟糕的解决方案是将first.py输出到一个文本文件并让second.py从那里读取它,希望它也不会相互矛盾,因为两个脚本都会同时尝试使用它?

3 个答案:

答案 0 :(得分:3)

使用这样的导入:

file1.py:

value = 1

def main():
     print("execute only if called directly")

if __name__ == "__main__":
    main()

并在file2.py中:

from file1 import value

确保将两个文件放在一个包中(目录必须包含__init__.py文件)。当然,如果文件位于另一个包中,您也可以访问该文件。

或者,您可以在file1.py中编写一个get_value()函数,该函数返回请求的值并导入此函数:

from file1 import get_value
value = get_value()

如果temp是一个经常更新的变量(因为我怀疑看你的代码),你可以做任何一个

1)编写一个函数(例如First.read_temp()),读取温度一次,然后导入并在Second.py中使用此函数或

2)从数据库中获取temp的最新值(如果时间延迟无关紧要)。

答案 1 :(得分:2)

使用void Available_firmware_version(){ char *version = (char *) malloc(2); strcpy(version, ""); FILE *fp; int status = 0; char path[PATH_MAX]; fp = popen("swift list Manto", "r"); if (fp == NULL){ printf("Error: Popen is NULL \n"); return; } while (fgets(path, PATH_MAX, fp) != NULL){ version = (char *) realloc(version, strlen(version) + strlen(path)); strcat(version, path); printf("%s\n", version); } status = pclose(fp); if (status == -1) { printf("Error: Popen not closed (pclose)\n"); return; } free(version); } 开始second.py。这只会将一个名称导入您的命名空间。

请记住,必须运行整个脚本from first import value才能使其正常运行。因此,如果您的脚本中有任何可运行的代码,请确保将其保护为类似if __name__ == '__main__'的行。

答案 2 :(得分:1)

INTRO

这会有点长,所以我写了一个介绍。

由于您试图让两个独立的进程相互通信,因此只能通过导入解决问题。一个进程必须写入数据,另一个进程必须读取它。您可以使用多种选项来执行此操作。这里有三个,但请记住还有其他方法:

  1. 让一个进程启动另一个进程并使用subprocess模块在​​它们之间进行通信。
  2. 使用Unix Domain Sockets,它类似于常规套接字,但可以通过Linux(或其他Unix实现)计算机上的命名文件进行访问。这将使用socket模块。
  3. 使用共享内存实现只是在共享内存中写入值。据我所知,没有内置模块可以完成独立的进程。
  4. 在上述三种方法中,第一种方法是最便携的,但你必须从另一种方法开始一个脚本。考虑到显示的代码,我无法想象这对你来说是个大问题。

    第二种方法仅适用于类Unix系统,我不希望它在Raspberry Pi上出现问题。它允许您完全独立地运行进程:它们只需要在它们之间共享套接字的名称,并且您实际上可以保证使用导入它们是相同的。我不会采用这种方法,因为它可能对你的情况有点过分了。

    我不知道有任何方法只使用内置模块来实现第三个选项。您可以使用像shm这样的库,但我不会详细介绍这种方法。

    代码

    在我解释如何实现第1项和第2项之前,我想建议稍微重构一下代码,以简化转换过程。我希望您在getdata中已经计划了Second.py功能。但是,我还建议进行更多更改,以简化此过程:

    <强> First.py

    # External module imports
    import time
    import os
    import datetime
    import MySQLdb
    
    import seven_segment
    
    def main():
        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()
    
        # Initialization
        sensor = "/sys/bus/w1/devices/28-011620ee98ee/w1_slave"
    
        while True:
            # Open the file for sensor
            with open(sensor) as file: 
                # Read all of the text in the file. 
                text = file.read()
            # 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
            # Send temperature over for further processing
            write_out(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)
    
    if __name__ == '__main__':
        main()
    

    <强> 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(get_temp()).rjust(3)
            for pos, digit in enumerate(s):
                for loop in range(7):
                    GPIO.output(segments[loop], num[digit][loop])
                    flag = (int(time.time()) % 2 == 0) and (pos == 1)
                    GPIO.output(25, flag)
                GPIO.output(digits[pos], 0)
                time.sleep(0.001)
                GPIO.output(digits[pos], 1)
    finally:
        GPIO.cleanup()
    

    大多数更改都是清理,例如在循环外定义常量项。关键的增加是write_outFirst.pyget_tempSecond.py的调用。

    另请注意,First的功能现在位于main函数中,该函数仅在__name__ == '__main__'时调用。这将允许您像以前一样从命令行运行First.py作为脚本。在import First内执行Second.py时,它不会运行所有代码,只需定义main之外的常量。

    子流程方法

    使用此方法,First.py必须启动Second.py,反之亦然。我将采用第一种方法,因为它看起来似乎有点简单。无论哪种方式,First的标准输出都将转到Second的标准输入。您可以将First.py更改为如下所示:

    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)
    

    在这里,首先启动Second.py并将温度值传递给Second的标准输入。 Here是一个相关的答案。 First.main现在必须接受一个子流程作为参数,需要将其传递给write_out

    在这种情况下,

    Second.py不需要任何修改:只是从stdin读取的get_temp的定义:

    def get_temp():
        temp = float(sys.in.readline())
    

    结论

    考虑到为使这项工作必须做的工作量,您可能想要完全考虑另一种方法。也许你可以定义一个在Second.py中执行额外处理的函数(类似于我在main中对First.py所做的处理)。然后,每当您获得新的温度读数时,您可以在First.py的后台线程中调用该函数。这将使您的代码更简单,更容易处理。假设您的函数名为process_temp,您可以在First.py中执行以下操作:

    import threading
    
    ...
    
    def write_out(temp):
        thread = threading.Thread(target=Second.process_temp, args=(temp,))
        thread.start()
    
    ...