простое сохранение / загрузка данных в python - PullRequest
9 голосов
/ 15 декабря 2010

Какой самый простой способ сохранить и загрузить данные в python, желательно в удобочитаемом формате вывода?

Сохраняемые / загружаемые данные состоят из двух векторов с плавающей точкой. В идеале эти векторы должны быть названы в файле (например, X и Y).

Мои текущие функции save() и load() используют file.readline(), file.write() и преобразование строки в число с плавающей точкой. Должно быть что-то лучше.

Ответы [ 7 ]

22 голосов
/ 15 декабря 2010

Самый простой способ получить удобочитаемый вывод - использовать формат сериализации, такой как JSON. Python содержит библиотеку json , которую можно использовать для сериализации данных в строку и из нее. Как и pickle , вы можете использовать это с объектом ввода-вывода, чтобы записать его в файл.

import json

file = open('/usr/data/application/json-dump.json', 'w+')
data = { "x": 12153535.232321, "y": 35234531.232322 }

json.dump(data, file)

Если вы хотите получить простую строку вместо ее выгрузки в файл, вы можете использовать json. dumps () вместо:

import json
print json.dumps({ "x": 12153535.232321, "y": 35234531.232322 })

Чтение из файла так же просто:

import json

file = open('/usr/data/application/json-dump.json', 'r')
print json.load(file)

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

9 голосов
/ 15 декабря 2010

Есть несколько вариантов - я точно не знаю, что вам нравится. Если два вектора имеют одинаковую длину, вы можете использовать numpy.savetxt() для сохранения ваших векторов, скажем x и y в виде столбцов:

 # saving:
 f = open("data", "w")
 f.write("# x y\n")        # column names
 numpy.savetxt(f, numpy.array([x, y]).T)
 # loading:
 x, y = numpy.loadtxt("data", unpack=True)

Если вы имеете дело с большими векторами чисел с плавающей точкой, вам, вероятно, все равно следует использовать NumPy.

7 голосов
/ 15 декабря 2010
  • Если это должно быть читаемым человеком, я бы тоже пошел с JSON.Если вам не нужно обмениваться им с людьми корпоративного типа, им больше нравится XML.: -)

  • Если бы это было человеческое редактируемое и не слишком сложное, я бы, вероятно, выбрал какой-то INI-подобный формат, например, дляпример configparser.

  • Если он сложный и его не нужно обменивать, я бы просто выбрал данные, если только они не очень сложные, в этом случае я быиспользуйте ZODB.

  • Если это много данных и их необходимо обменять, я бы использовал SQL.

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

2 голосов
/ 15 декабря 2010

Простой формат сериализации, который легко читается обоими людьми: JSON .

Вы можете использовать модуль json Python.

1 голос
/ 23 мая 2019

Вот пример Encoder, пока вы, вероятно, не захотите написать для Body class:

# add this to your code
class BodyEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, np.ndarray):
            return obj.tolist()
        if hasattr(obj, '__jsonencode__'):
            return obj.__jsonencode__()
        if isinstance(obj, set):
            return list(obj)
        return obj.__dict__

    # Here you construct your way to dump your data for each instance
    # you need to customize this function
    def deserialize(data):
        bodies = [Body(d["name"],d["mass"],np.array(d["p"]),np.array(d["v"])) for d in data["bodies"]]
        axis_range = data["axis_range"]
        timescale = data["timescale"]
        return bodies, axis_range, timescale

    # Here you construct your way to load your data for each instance
    # you need to customize this function
    def serialize(data):
        file = open(FILE_NAME, 'w+')
        json.dump(data, file, cls=BodyEncoder, indent=4)
        print("Dumping Parameters of the Latest Run")
        print(json.dumps(data, cls=BodyEncoder, indent=4))

Вот пример класса, который я хочу сериализовать:

class Body(object):
    # you do not need to change your class structure
    def __init__(self, name, mass, p, v=(0.0, 0.0, 0.0)):
        # init variables like normal
        self.name = name
        self.mass = mass
        self.p = p
        self.v = v
        self.f = np.array([0.0, 0.0, 0.0])

    def attraction(self, other):
        # not important functions that I wrote...

Вот как сериализовать:

# you need to customize this function
def serialize_everything():
    bodies, axis_range, timescale = generate_data_to_serialize()

    data = {"bodies": bodies, "axis_range": axis_range, "timescale": timescale}
    BodyEncoder.serialize(data)

Вот как сделать дамп:

def dump_everything():
    data = json.loads(open(FILE_NAME, "r").read())
    return BodyEncoder.deserialize(data)
0 голосов
/ 06 ноября 2016

Как я прокомментировал в принятом ответе, используя numpy, это можно сделать с помощью простого однострочного:

Предполагается, что numpy импортировано как np (что является обычной практикой),

np.savetxt('xy.txt', np.array([x, y]).T, fmt="%.3f", header="x   y")

сохранит данные в (необязательном) формате и

x, y = np.loadtxt('xy.txt', unpack=True)

загрузит его.

Файл xy.txt будет выглядеть следующим образом:

# x   y
1.000 1.000
1.500 2.250
2.000 4.000
2.500 6.250
3.000 9.000

Обратите внимание, что строка формата fmt=... является необязательной, но если цель - удобочитаемость, она может оказаться весьма полезной. Если используется, он указывается с использованием обычных printf -подобных кодов (в моем примере: число с плавающей запятой с 3 десятичными знаками).

0 голосов
/ 15 декабря 2010

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

Как насчет следующей реализации скелета. Он просто сохраняет данные в виде key=value пар и работает со списками, кортежами и многими другими вещами.

    def save(fname, **kwargs):
      f = open(fname, "wt")
      for k, v in kwargs.items():
        print >>f, "%s=%s" % (k, repr(v))
      f.close()

    def load(fname):
      ret = {}
      for line in open(fname, "rt"):
        k, v = line.strip().split("=", 1)
        ret[k] = eval(v)
      return ret

    x = [1, 2, 3]
    y = [2.0, 1e15, -10.3]
    save("data.txt", x=x, y=y)
    d = load("data.txt")
    print d["x"]
    print d["y"]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...