【问题标题】:python gdata, extracting numbers from outputpython gdata,从输出中提取数字
【发布时间】:2013-05-14 03:00:51
【问题描述】:

我还是 Python 的新手,我一直在使用脚本从我的 Raspberry Pi 获取系统信息,例如 cpu temp 等,并将其导入到谷歌文档电子表格中。我的目标是从输出中提取数字,格式为temp=54.1'C。我只需要这些数字就能够随时间绘制数据...

我正在使用:

import gdata.spreadsheet.service
import os
import subprocess
import re

email = 'myemail@gmail.com'
password = 'mypassword'

spreadsheet_key = 'sjdaf;ljaslfjasljdgasjdflasdjfgkjvja'
worksheet_id = '1'

def temp():
   command = "/opt/vc/bin/vcgencmd measure_temp"
   proc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
   output = proc.stdout.read()
   return output

def main():
   spr_client = gdata.spreadsheet.service.SpreadsheetsService()
   spr_client.email = email
   spr_client.password = password
   spr_client.ProgrammaticLogin()

   dict = {}
   dict['temp'] = temp()

   entry = spr_client.InsertRow(dict, spreadsheet_key, worksheet_id)

if __name__ == '__main__':
      try:
         main()
      except:
         print "Insert Row Failed!"

以上给出了标准结果。我尝试修改 re.findall(),但无法获得正确的位置或条件的正确组合(r、'/d+'、s 和其他东西)以使其仅返回数字 54.1.. . 我基本上以“插入行失败”结束

任何指导将不胜感激。谢谢!

【问题讨论】:

  • 当您说“标准结果”时,大概是指Insert Row Failed!,是吗?在这个特定的 sn-p 中,我没有看到您正在做任何事情来搜索您描述的 temp 键;你忘记了一些代码吗?
  • 好吧,按照标准结果,我的意思是第一段中提到的“temp=54.1'C”。当我开始尝试在各种位置和配置中插入 re.findall() 时,我得到了异常......
  • 命令是“/opt/vc/bin/vcgencmd measure_temp”,您可以在终端中输入它,它会给出 temp=54.1'C。这个脚本的设置方式,它在我的谷歌文档的一个单元格中给了我那个文本字符串。然后它继续添加一行并在每次运行时打印结果......这就是我想要的。我在 crontab 中设置它,然后在计时器上获取数据......
  • 啊,我明白了。所以你需要添加一些处理来从命令行函数返回的字符串中获取值(例如54.1,尽管它可能是半任意十进制),对吗?
  • 是的,我相信温度会有一位小数

标签: python gdata


【解决方案1】:

您使用re 走在正确的轨道上;你最好的选择(假设小数可以是任意的,等等)是这样的:

import re

def temp():
    command = "/opt/vc/bin/vcgencmd measure_temp"
    proc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
    output = proc.stdout.read()

    # Build the regex. Use () to capture the group; we want any number of
    # digits \d or decimal points \. that is preceded by temp= and
    # followed by 'C
    temp_regex = re.compile(r'temp=([\d\.]*)\'C')
    matches = re.findall(temp_regex, output)   # now matches = ['54.1']

    temp = float(matches[0])
    return temp

正则表达式捕获数字和小数位的任意组合(例如,12.34.56 将被匹配);如果有必要,您可以将其限制为只允许一个小数位,但如果您可以相信您返回的数据格式正确,那么这比看起来值得做的工作更多。如果您确实希望数字更精确,您可以像这样编译正则表达式(小数位前至少有一个数字,小数位后面正好有一个):

temp_regex = re.compile(r'temp=(\d+.\d)\'C')

再次,我们使用括号捕获表达式(捕获的组是 findall 的 returned),但这一次,增加了我们正在寻找的内容的特异性。这将捕获像123.4 这样的任何数字,但不会捕获.4 而不是123. 如果您发现需要将其扩大一点但仍然只需要一位小数:

temp_regex = re.compile(r'temp=(\d+.\d+)\'C')

这将捕获小数点后至少有一个数字的任何数字,因此1234.5678 将匹配但1234. 不会匹配,.1234 不会匹配。

作为使用re.findall() 的替代方法,您可以使用re.match(),它返回match objects。然后你的用法看起来像这样(使用直接方法,而不是预编译字符串:

match = re.match(r'temp=(\d+.\d+)\'C', output)
if match:
    temp = float(match.group(1))   # get the first matching group captured by ()
else:
    pass   # You should add some error handling here

这比我上面提到的re.findall() 更清楚的一件事是,如果没有捕获任何内容,那么您就有问题了,您需要弄清楚如何处理它。


您可以在 Regular-Expressions.info 上查看其他方法来改变它,这是我在网络上找到的关于该主题的快速资源的最佳网站。

【讨论】:

  • 感谢您花时间发布示例。不幸的是,我似乎无法实现它们。我已经尝试了所有三种形式,尝试将其修剪下来去除浮动。我会继续努力,我想我会读一些关于 're.compile()' 的文章,我在这里看到的大多数例子只是直接使用 're.findall()' ......也许我有太多的实例代码中的“临时”搞砸了?
  • 好的,在 IDLE 中运行 re.findall,由于“C”,它一直给我一个语法错误,我必须弄清楚如何让它忽略第一个刻度线 (')
  • 如果你重复使用temp,那可能确实搞砸了,这就是我加入'C的原因。请注意,该模式实际上转义了引号:\'。我完全按照你的模式测试了这个,它工作得很好。你没有必须使用re.compile();我这样做是因为它可以更容易地看到你在哪一步。此外,您可以使用re.match() 而不是re.findall(),这实际上可能会产生更好的行为;我将在问题中添加一条说明如何做到这一点。
  • 如果你能给我它返回的字符串的更长版本,我可以确保正则表达式正确地处理它。
  • 谢谢,我会在工作时检查一下(在工作中),我必须通过 ssh 连接到我的 Pi 并尝试一下……它返回的字符串的更长版本?我们说的是“temp=54.1'C”吗?返回的唯一额外内容是一些空格或换行符,我一直在使用 'output = output.replace("\n","")' 删除它们我仍然想知道是否应该使用双引号单的。我似乎在整个脚本中都有。应该统一吗?
【解决方案2】:

好吧,我已经花了太多时间搞砸这个了。我似乎无法让output = proc.stdout.read() 给我任何东西。我尝试了几十种re 的组合,但都没有成功。

然后我开始研究 replace() 方法。这可能不是最巧妙的方法,但我知道输出将始终采用“temp=XX.X'C”的形式(X 是数字),所以我最终这样做了:

def temp():
   command = "/opt/vc/bin/vcgencmd measure_temp"
   proc = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
   output = proc.stdout.read()
   output1 = output.replace("temp=","")
   output2 = output1.replace("'C","")
   return output2

它成功了!它在 Google 电子表格中显示为我需要的数字。

无论如何,感谢您的帮助,我将继续尝试在其他应用程序中实现re,也许我会找出为什么我无法让它与它一起工作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-11-04
    • 1970-01-01
    相关资源
    最近更新 更多