2017-02-15 9 views
0

Я запускаю свою собственную систему управления пулом, и я хотел реализовать копирование определенных параметров системы в плоский файл для обработки с помощью веб-интерфейса, над которым я работаю. Поскольку есть только несколько записей, мне понравился ConfigParser для работы.Использование ConfigParser в Python - проверяет OK, но удаляет файл после развертывания

Я построил тестовую установку, и она отлично работала. Вот этот код:

import ConfigParser 

config = ConfigParser.ConfigParser() 
get_pool_level_resistance_value = 870 


def read_system_status_values(file, section, system): 
    config.read(file) 
    current_status = config.get(section, system) 
    print("Our current {} is {}.".format(system, current_status)) 


def update_system_status_values(file, section, system, value): 
    cfgfile = open(file, 'w') 
    config.set(section, system, value) 
    config.write(cfgfile) 
    cfgfile.close() 
    print("{} updated to {}".format(system, value)) 


def read_test(): 
    read_system_status_values("current_system_status", "system_status", 
           "pool_level_resistance_value") 


def write_test(): 
    update_system_status_values("current_system_status", "system_status", 
           "pool_level_resistance_value", 
           get_pool_level_resistance_value) 


read_test() 
write_test() 
read_test() 

Это мой конфигурационный файл "current_system_status":

[system_status] 
running_status = True 
fill_control_manual_disable = False 
pump_running = True 
pump_watts = 865 
pool_level_resistance_value = 680 
pool_level = MIDWAY 
pool_is_filling = False 
pool_is_filling_auto = False 
pool_is_filling_manual = False 
pool_current_temp = 61 
pool_current_ph = 7.2 
pool_current_orp = 400 
sprinklers_running = False 
pool_level_sensor_battery_voltage = 3.2 
pool_temp_sensor_battery_voltage = 3.2 
pool_level_sensor_time_delta = 32 
pool_temp_sensor_time_delta = 18 

Когда я запускаю мой тестовый файл я получаю этот выход:

ssh://[email protected]:22/usr/bin/python -u /root/pool_control/V3.2/system_status.py 
Our current pool_level_resistance_value is 350. 
pool_level_resistance_value updated to 870 
Our current pool_level_resistance_value is 870. 

Process finished with exit code 0 

Это точно так, как ожидается. Однако, когда я двигаю его к моему основному модулю pool_sensors.py, в любое время я запускаю его я получаю следующее сообщение об ошибке:

Traceback (most recent call last): 
    File "/root/pool_control/V3.2/pool_sensors.py", line 58, in update_system_status_values 
    config.set(section, system, value) 
    File "/usr/lib/python2.7/ConfigParser.py", line 396, in set 
    raise NoSectionError(section) 
ConfigParser.NoSectionError: No section: 'system_status' 

Process finished with exit code 1 

Я тогда отлажен (используя PyCharm) и, как я шел через код, как только он получает в этой строке в коде:

cfgfile = open(file, 'w') 

он стирает мой файл полностью, и, следовательно, я получаю NoSectionError. Когда я отлаживаю свой тестовый файл и добирается до той же самой строки кода, он открывает файл и обновляет его, как ожидалось.

И тестовый файл, и фактический файл находятся в одном каталоге на одном компьютере с использованием той же самой версии всего. Код, который открывает и записывает файлы, является точным дубликатом тестового кода, за исключением заявления отладочной печати в «производственном» коде.

Я пробовал различные методы, в том числе:

cfgfile = open(file, 'w') 
cfgfile = open(file, 'r') 
cfgfile = open(file, 'wb') 

, но независимо от того, какой из них я использую, когда я включил тестовый код в моем файле производства, как только она попадает, что линия его полностью стирает файл, против его обновления, как это делают мои тестовые файлы.

Вот это pertenent строки кода, где я называю его:

import pooldb # Database information 
import mysql.connector 
from mysql.connector import errorcode 
import time 
import notifications 
import logging 
import ConfigParser 

DEBUG = pooldb.DEBUG 
config = ConfigParser.ConfigParser() 

def read_system_status_values(file, section, system): 
    config.read(file) 
    current_status = config.get(section, system) 
    if DEBUG: 
     print("Our current {} is {}.".format(system, current_status)) 


def update_system_status_values(file, section, system, value): 
    cfgfile = open(file, 'w') 
    config.set(section, system, value) 
    config.write(cfgfile) 
    cfgfile.close() 
    if DEBUG: 
     print("{} updated to {}".format(system,value)) 

def get_pool_level_resistance(): 
    """ Function to get the current level of our pool from our MySQL DB. """ 
    global get_pool_level 
    try: 
     cnx = mysql.connector.connect(user=pooldb.username, 
             password=pooldb.password, 
             host=pooldb.servername, 
             database=pooldb.emoncms_db) 
    except mysql.connector.Error as err: 
     if err.errno == errorcode.ER_ACCESS_DENIED_ERROR: 
      logger.error(
       'Database connection failure: Check your username and password') 
      if DEBUG: 
       print(
        "Database connection failure: Check your username and " 
        "password") 
     elif err.errno == errorcode.ER_BAD_DB_ERROR: 
      logger.error('Database does not exist. Please check your settings.') 
      if DEBUG: 
       print("Database does not exist. Please check your settings.") 
     else: 
      logger.error(
       'Unknown database error, please check all of your settings.') 
      if DEBUG: 
       print(
        "Unknown database error, please check all of your " 
        "settings.") 
    else: 
     cursor = cnx.cursor(buffered=True) 
     cursor.execute(("SELECT data FROM `%s` ORDER by time DESC LIMIT 1") % (
      pooldb.pool_resistance_table)) 

     for data in cursor: 
      get_pool_level_resistance_value = int("%1.0f" % data) 
      cursor.close() 
      logger.info("Pool Resistance is: %s", 
         get_pool_level_resistance_value) 
      if DEBUG: 
       print(
        "pool_sensors: Pool Resistance is: %s " % 
        get_pool_level_resistance_value) 
       print(
        "pooldb: Static critical pool level resistance set at (" 
        "%s)." % 
        pooldb.pool_resistance_critical_level) 
       print(
        "pooldb: Static normal pool level resistance set at (%s)." % 
        pooldb.pool_resistance_ok_level) 
     cnx.close() 

    print("We made it here with a resistance of (%s)" % 
      get_pool_level_resistance_value) 
    update_system_status_values("current_system_status", 
           "system_status", 
           "pool_level_resistance_value", 
           get_pool_level_resistance_value) 

    if get_pool_level_resistance_value >= pooldb.pool_resistance_critical_level: 
     get_pool_level = "LOW" 
     update_system_status_values("current_system_status", 
            "system_status", 
            "pool_level", 
            get_pool_level) 
     if DEBUG: 
      print("get_pool_level_resistance() returned pool_level = LOW") 
    else: 
     if get_pool_level_resistance_value <= pooldb.pool_resistance_ok_level: 
      get_pool_level = "OK" 
      update_system_status_values("current_system_status", 
             "system_status", 
             "pool_level", 
             get_pool_level) 
      if DEBUG: 
       print("get_pool_level_resistance() returned pool_level = OK") 

    if DEBUG: 
     print("Our Pool Level is %s." % get_pool_level) 

    return get_pool_level 

Я подозреваю, что это могло бы иметь что-то делать с другой импорт может быть конфликтует с открытым (файл, «W»).

Мой главный модуль pool_fill_control.py и имеет следующие импорта:

import pooldb # Configuration information 
import datetime 
import logging 
import os 
import socket 
import subprocess 
import threading 
import time 
import RPi.GPIO as GPIO # Import GPIO Library 
import mysql.connector 
import requests 
import serial 
from mysql.connector import errorcode 
import notifications 
import pool_sensors 
import ConfigParser 

внутри функции в этом модуле, он затем вызывает мой модуль pool_sensors.py, показанный выше, используя следующую строку кода:

get_pool_level = pool_sensors.get_pool_level_resistance() 

Любое сообщение или помощь относительно того, почему он работает в одну сторону, а не другую, будет весьма признателен.

ответ

0

Ну, достаточно интересно после проведения большего исследования и поиска по линии через код, я понял, что единственное, что я делал в своем тестовом файле, - это сначала прочитать файл перед тем, как писать ему.

Так что я изменил код следующим образом:

Старый Код:

def update_system_status_values(file, section, system, value): 
    cfgfile = open(file, 'w') 
    config.set(section, system, value) 
    config.write(cfgfile) 
    cfgfile.close() 
    if DEBUG: 
     print("{} updated to {}".format(system,value)) 

Новый код (спасибо @ShadowRanger)

def update_system_status_values(file, section, system, value): 
    config.read(file) 
    cfgfile = open('tempfile', 'w') 
    config.set(section, system, value) 
    config.write(cfgfile) 
    cfgfile.close() 
    os.rename('tempfile', file) 
    if DEBUG: 
     print("{} updated to {}".format(system, value)) 

и теперь он работает как шарм !!

Эти шаги прямо сейчас:

1) Почитайте

2) Открыть временный файл

3) Обновление это

4) Написать временный файл

5) Закрыть временный файл

6) Переименуйте файл temp по основному файлу

+1

Примечание. Лучшим решением может быть «открыть» новый «tempfile.NamedTemporaryFile» в том же каталоге, что и исходный, заполнить его, а затем использовать 'os.replace' для перемещения нового файла по старому файлу атомарно. Если ваш код может включать даже потоки, или исключения могут возникать во время написания нового параметра, это позволяет избежать риска повреждения ваших данных; вы либо преуспеете, либо атомарно замените старый на новый, либо вы потерпите неудачу, а старый файл останется нетронутым. – ShadowRanger

+0

@ShadowRanger - Это звучит неплохо. Является ли идея, что вы читаете содержимое конфигурационного файла, вносите изменения в файл конфигурации в памяти (config.set), затем открываете новый файл temp, записываете конфигурацию в этот файл (config.write (tempfile.NamedTemporaryFile) , закройте этот файл, а затем используйте os.replace, чтобы перезаписать исходный файл, или мне нужно будет каждый раз обновлять конфигурационный файл с нуля? – Richard

+1

Решение, как вы его описываете, будет «воссоздавать с нуля» в том смысле, что это весь новый файл каждый раз, когда вы выполняете это обновление, но это не имеет большого значения, если вы не часто переписываете. Не знаете, что вы подразумеваете под «воссоздать с нуля», который отличается от описанного вами процесса. – ShadowRanger

 Смежные вопросы

  • Нет связанных вопросов^_^