数日前から、プログラムの再起動時にパーサー用の設定クラスで設定された設定が永続的ではないという問題がありました。この問題はWindowsのみで発生しますが、Python x86およびx64環境でも、PyInstallerを使用してコンパイルした場合でも発生します。また、プログラムが管理者として実行されるかどうかは関係ありません。 プログラムが最初に実行されるとき、write_def(self)
がコンストラクタによって呼び出されます。この関数は、指定されたファイルにデフォルト値を正しく書き出します。その後、read_set(self)
が呼び出され、クラス変数が設定されます。これらのクラス変数は、デフォルト値と一致します。 別のファイルでは、namely frames.py,write_set(self)
が呼び出され、すべての設定が引数として渡されます。 print文を使って、私はwrite_set(self)
関数が正しい値を受け取ると主張しました。ファイルに設定を書き込むときにエラーは発生せず、read_set(self)
を再度実行すると、新しい設定が正しく読み込まれ、これもGUIに表示されます。 しかし、プログラムを閉じてもう一度実行すると、デフォルト設定が再度表示されます。これは私が期待した動作ではありません。Python 2.7でファイルに正しく書き込まれなかった変更
以下、cPickle
を実装する設定クラスを追加しました。 pickle
を使用する場合の動作は同じです。 this fileのようにshelve
を使用する場合、動作は同じです。 dill
を使用する場合、動作は同じです。 ConfigParser.RawConfigParser
(これまでにリンクされたGitHubリポジトリのconfigparserブランチにある)を実装すると、動作は同じです。さらに、設定ファイルをテキストエディタで表示すると、ファイルの設定は更新されません。
Linux(Ubuntu 16.04.1 LTS with Python 2.7)で同じコードを実行すると、すべてがpickle
とshelve
バージョンで期待通りに機能します。設定は正しく保存され、ファイルからロードされます。私は何か間違っているのですか?それはPythonのWindows固有の問題ですか?
ありがとうございました!
RedFantom。
# Written by RedFantom, Wing Commander of Thranta Squadron and Daethyra, Squadron Leader of Thranta Squadron
# Thranta Squadron GSF CombatLog Parser, Copyright (C) 2016 by RedFantom and Daethyra
# For license see LICENSE
# UI imports
import tkMessageBox
# General imports
import getpass
import os
import cPickle
# Own modules
import vars
# Class with default settings for in the settings file
class defaults:
# Version to display in settings tab
version = "2.0.0_alpha"
# Path to get the CombatLogs from
cl_path = 'C:/Users/' + getpass.getuser() + "/Documents/Star Wars - The Old Republic/CombatLogs"
# Automatically send and retrieve names and hashes of ID numbers from the remote server
auto_ident = str(False)
# Address and port of the remote server
server = ("thrantasquadron.tk", 83)
# Automatically upload CombatLogs as they are parsed to the remote server
auto_upl = str(False)
# Enable the overlay
overlay = str(True)
# Set the overlay opacity, or transparency
opacity = str(1.0)
# Set the overlay size
size = "big"
# Set the corner the overlay will be displayed in
pos = "TL"
# Set the defaults style
style = "plastik"
# Class that loads, stores and saves settings
class settings:
# Set the file_name for use by other functions
def __init__(self, file_name = "settings.ini"):
self.file_name = file_name
# Set the install path in the vars module
vars.install_path = os.getcwd()
# Check for the existence of the specified settings_file
if self.file_name not in os.listdir(vars.install_path):
print "[DEBUG] Settings file could not be found. Creating a new file with default settings"
self.write_def()
self.read_set()
else:
try:
self.read_set()
except:
tkMessageBox.showerror("Error", "Settings file available, but it could not be read. Writing defaults.")
self.write_def()
vars.path = self.cl_path
# Read the settings from a file containing a pickle and store them as class variables
def read_set(self):
with open(self.file_name, "r") as settings_file_object:
settings_dict = cPickle.load(settings_file_object)
self.version = settings_dict["version"]
self.cl_path = settings_dict["cl_path"]
self.auto_ident = settings_dict["auto_ident"]
self.server = settings_dict["server"]
self.auto_upl = settings_dict["auto_upl"]
self.overlay = settings_dict["overlay"]
self.opacity = settings_dict["opacity"]
self.size = settings_dict["size"]
self.pos = settings_dict["pos"]
self.style = settings_dict["style"]
# Write the defaults settings found in the class defaults to a pickle in a file
def write_def(self):
settings_dict = {"version":defaults.version,
"cl_path":defaults.cl_path,
"auto_ident":bool(defaults.auto_ident),
"server":defaults.server,
"auto_upl":bool(defaults.auto_upl),
"overlay":bool(defaults.overlay),
"opacity":float(defaults.opacity),
"size":defaults.size,
"pos":defaults.pos,
"style":defaults.style
}
with open(self.file_name, "w") as settings_file:
cPickle.dump(settings_dict, settings_file)
# Write the settings passed as arguments to a pickle in a file
# Setting defaults to default if not specified, so all settings are always written
def write_set(self, version=defaults.version, cl_path=defaults.cl_path,
auto_ident=defaults.auto_ident, server=defaults.server,
auto_upl=defaults.auto_upl, overlay=defaults.overlay,
opacity=defaults.opacity, size=defaults.size, pos=defaults.pos,
style=defaults.style):
settings_dict = {"version":version,
"cl_path":cl_path,
"auto_ident":bool(auto_ident),
"server":server,
"auto_upl":bool(auto_upl),
"overlay":bool(overlay),
"opacity":float(opacity),
"size":str(size),
"pos":pos,
"style":style
}
with open(self.file_name, "w") as settings_file_object:
cPickle.dump(settings_dict, settings_file_object)
self.read_set()