A friend of mine ran into some trouble where he kept losing edge information on his models. He asked me if I could make something to save out the hard edges to a file so they could be loaded back on if he lost them.

Way quicker version

To save:

import maya.api.OpenMaya as om

selection_list = om.MSelectionList()
dag_path = selection_list.getDagPath(0)
edge_it = om.MItMeshEdge(dag_path)

hard_edge_info = []
while not edge_it.isDone():
    # save a list of the edge number and a bool whether it's a soft edge
    hard_edge_info.append([int(edge_it.index()), edge_it.isSmooth])
    edge_it.next()

To load:

selection_list = om.MSelectionList()
dag_path = selection_list.getDagPath(0)
mfn_mesh = om.MFnMesh(dag_path)

# zip over the small 2 member lists to end up with 2 big lists.
edge_numbers, edge_hardness = zip(*hard_edge_info)

mfn_mesh.setEdgeSmoothings(edge_numbers, edge_hardness)
mfn_mesh.cleanupEdgeSmoothing()
mfn_mesh.updateSurface()

Old version

import pymel.core as pm

import os
import re

from PySide2.QtCore import *
from PySide2.QtUiTools import *
from PySide2.QtGui import *
from PySide2.QtWidgets import *

import nv_utils.qt_utils as qt_utils
import nv_utils.io_utils as io_utils
import nv_maya_utils.general as general
import nv_maya_utils.decorators as maya_decorators



class HardEdgeSaverWindow(QMainWindow):
    def __init__(self, parent=general.get_maya_main_window()):
        qt_utils.delete_window(self)
        super(HardEdgeSaverWindow, self).__init__(parent)

        widget = QWidget()
        layout = QVBoxLayout()
        btn_save = QPushButton("Save hard edges")
        btn_load = QPushButton("Load hard edges")

        btn_save.clicked.connect(self.save)
        btn_load.clicked.connect(self.load_edges_from_file)

        layout.addWidget(btn_save)
        layout.addWidget(btn_load)
        widget.setLayout(layout)

        self.setWindowTitle("Hard Edge Saver")
        self.setWindowFlags(Qt.Dialog)
        self.setCentralWidget(widget)

        self.scene_dict = self.get_scene_dict()

    @maya_decorators.progress_window(status="Saving hard edges...")
    def save(self):
        if pm.sceneName() == "":
            general.show_viewport_message("Save the scene first", color="red")
            return

        meshes = self.get_all_or_selected_meshes()

        for mesh in meshes:
            self.save.update_progress(100/len(meshes),"Saving %s..." % mesh.name())
            self.scene_dict[mesh.name()] = self.get_hard_edges(mesh)

        io_utils.write_json(self.scene_dict, self.get_file_path())
        general.show_viewport_message("Saved to %s" % self.get_file_path(), color="green")

    def get_hard_edges(self, mesh):
        edge = 0x8000
        off = 0
        hard = 1
        smooth = 2
        all_and_next = 3

        pm.select(mesh)
        pm.polySelectConstraint(mode=all_and_next, type=edge, smoothness=hard)
        hard_edges = [re.search(r"\[(.*?)\]", edge.name()).group(0) for edge in pm.selected()]

        pm.polySelectConstraint(mode=off, type=0x8000, smoothness=hard)
        pm.select(None)

        return hard_edges

    @general.progress_window_decorator(status="Loading hard edges...")
    def load_edges_from_file(self):
        with pm.UndoChunk():
            meshes = self.get_all_or_selected_meshes()

            for mesh in meshes:
                hard_edges = io_utils.read_json(self.get_file_path()).get(mesh.name())
                if hard_edges is not None:
                    self.load_edges_from_file.update_progress(100/len(meshes), "Loading %s..." % mesh.name())
                    selection_list = ["%s.e%s" % (mesh.name(), edge_number) for edge_number in hard_edges]

                    pm.select(selection_list)
                    pm.polySoftEdge(angle=0, constructionHistory=1)
                    pm.bakePartialHistory(prePostDeformers=True)

            pm.select(None)

    def get_file_path(self):
        scene_name = os.path.basename(pm.sceneName())
        scene_name_no_ext = scene_name.split(".")[0]
        scene_folder = os.path.dirname(pm.sceneName())

        file_path = os.path.join(scene_folder, "%s_hard_edges.json" % scene_name_no_ext)
        return file_path

    def get_scene_dict(self):
        if os.path.isfile(self.get_file_path()):
           return io_utils.read_json(self.get_file_path())
        else:
           return {}

    def get_all_or_selected_meshes(self):
        meshes = []
        for node in pm.ls(selection=True, type="transform", long=True):
            try:
                if node.getShape().type() == "mesh":
                    meshes.append(node)
            except:
                pass

        if not meshes:
            for node in pm.ls(type="transform", long=True):
                try:
                    if node.getShape().type() == "mesh":
                        meshes.append(node)
                except:
                    pass

        return meshes