【问题标题】:Passing a single variable from one python program to another program将单个变量从一个 python 程序传递到另一个程序
【发布时间】:2017-04-26 10:23:19
【问题描述】:

我知道有人问过这个问题,但是每次示例都与我想要做的不同或更复杂时。

First.py

value = 10 #This variable should go to the Second script

第二个.py

newdata = value #This variable should come from the First script, 10

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

如果有什么不同,我也想要 v2.7。

谢谢

这是我的代码:{我要传递给 Second.py 的变量是 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)

第二个.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 从那里读取它,希望这也不会矛盾,因为两个脚本会同时尝试使用它?

【问题讨论】:

  • 导入 Second.py 调用其函数之一并传递值
  • @nishantkumar 也许您能用示例代码详细说明一下吗?谢谢。
  • 请正确缩进您的代码。
  • 另外,我怀疑此更新完全评估了我的回答。 @nishant-kumar 做到了,除非有一点遗漏。
  • 仍在等待您修复代码中的缩进,以便我可以看到您的 while 循环在哪里结束,等等...

标签: python python-2.7 raspberry-pi gpio


【解决方案1】:

使用这样的导入:

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 的最新值(如果时间延迟无关紧要)。

【讨论】:

  • 不错的答案,但我开始认为 OP 是在谈论跨进程通信,而不仅仅是将一个模块的一部分导入另一个模块。
  • 好的,谢谢。我听到你在说什么。我更新了我的答案。
【解决方案2】:

from first import value 开头second.py。这只会将那个名称导入您的命名空间。

请记住,必须运行整个脚本 first 才能使其工作。因此,如果您的脚本中有任何可运行的代码,请确保将其保护为像 if __name__ == '__main__' 这样的行。

【讨论】:

  • 我实际上从未使用过导入防护!能给我举个例子吗?据我了解,必须运行 First.py 才能自行执行 Second.py?
  • 对不起,我刚刚意识到这是错误的术语。几分钟后,我将在我离开手机后扩展我的答案。同时,我已经更新了一个链接。
【解决方案3】:

简介

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

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

  1. 让一个进程启动另一个进程并使用subprocess 模块在它们之间进行通信。
  2. 使用Unix Domain Sockets,它类似于常规套接字,但可以通过Linux(或其他Unix 实现)机器上的命名文件访问。这将使用 socket 模块。
  3. 使用共享内存实现仅将值写入共享内存。据我所知,没有内置模块可以对完全独立的进程执行此操作。

在上述三种方法中,第一种是最可移植的,但您必须从另一个脚本开始。鉴于显示的代码,我无法想象这对您来说是个大问题。

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

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

代码

在我解释如何实现第 1 项和第 2 项之前,我想建议对您的代码进行一些重组,以使转换过程更容易。我喜欢你已经在Second.py 中计划了一个getdata 功能。但是,我建议您进行更多更改以简化此过程:

First.py

# 外部模块导入 进口时间 导入操作系统 导入日期时间 导入 MySQL 数据库 导入七段 def main(): os.system('sudo modprobe w1-gpio') os.system('sudo modprobe w1-therm') # 连接到mysql db = MySQLdb.connect("localhost","zikmir","gforce","temp_database") 游标 = db.cursor() # 初始化 传感器 =“/sys/bus/w1/devices/28-011620ee98ee/w1_slave” 而真: # 打开传感器文件 打开(传感器)作为文件: # 读取文件中的所有文本。 text = file.read() # 用新行 (\n) 分割文本并选择第二行。 second_line = text.split("\n")[1] # 将行拆分为单词,参考空格,选择第10个单词(从0开始计数)。 temp_data = second_line.split(" ")[9] # 前两个字符是“t=”,所以去掉它们并将温度从字符串转换为数字。 临时 = 浮动(temp_data[2:]) # 将小数点放在正确的位置并显示出来。 温度 = 温度 / 1000 # 显示时间 打印 datetime.datetime.now(), temp # 发送温度以进行进一步处理 写出(临时) # 将数据推送到 mySQL sql = "插入到 time_temp 值(now(),%s)" cursor.execute (sql,(temp,)) db.commit() # 等待 5 秒 七段.getdata(临时) 时间.sleep(5) 如果 __name__ == '__main__': 主要的()

Second.py

导入 RPi.GPIO 作为 GPIO 进口时间 GPIO.setmode(GPIO.BCM) # 7seg 引脚的 GPIO 端口 段 = (11,2,23,8,7,10,18,25) # 7seg_segment_pins (11,7,4,2,1,10,5,3) + 100R 内联 分段分段: GPIO.setup(段,GPIO.OUT) GPIO.输出(段,0) # 数字 0-3 引脚的 GPIO 端口 数字 = (22,27,17) # 7seg_digit_pins (12,9,8) 数字分别为 0-3 对于数字中的数字: GPIO.setup(数字,GPIO.OUT) GPIO.输出(数字,1) 数 = { ' ': (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), } 尝试: 而真: s = str(get_temp()).rjust(3) 对于 pos,枚举中的数字: 范围内的 for 循环(7): GPIO.output(segments[loop], num[digit][loop]) 标志 = (int(time.time()) % 2 == 0) 和 (pos == 1) GPIO.output(25, flag) GPIO.output(digits[pos], 0) 时间.sleep(0.001) GPIO.output(digits[pos], 1) 最后: GPIO.cleanup()

大部分更改都是清理,例如在循环外定义常量项。增加的主要内容是在First.py 中对write_out 的调用以及在Second.py 中对get_temp 的调用。

还要注意First 的功能现在位于main 函数中,该函数仅在__name__ == '__main__' 时被调用。这将允许您像以前一样从命令行将First.py 作为脚本运行。当您在Second.py 中执行import First 时,它不会运行所有代码,只需定义您在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 在这种情况下不需要任何修改:只需一个从标准输入读取的get_temp 的定义:

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

结论

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

import threading

...

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

...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-09-23
    • 1970-01-01
    • 2010-11-18
    • 2015-10-23
    • 1970-01-01
    • 2010-10-11
    • 1970-01-01
    • 2013-04-01
    相关资源
    最近更新 更多