0

I'm trying to execute the Slyr : lyr_to_qml.py script (a script written by NorthRoad) in a standalone app. I'm having trouble running it, I get an "ModuleNotFoundError: No module named 'qgis'". I tried to change my the paths without any success. Here is the script :

from qgis.core import (Qgis,
                   QgsProcessingParameterFile,
                   QgsProcessingParameterFileDestination,
                   QgsProcessingOutputString,
                   QgsProcessingException)

from .algorithm import SlyrAlgorithm from ..gui_utils import GuiUtils from ...converters.context import Context from ...converters.layers import LayerConverter from ...parser.exceptions import (UnreadableSymbolException, NotImplementedException, UnknownClsidException, RequiresLicenseException) from ...parser.objects.group_layer import GroupLayer from ...parser.stream import Stream

try: from qgis.core import QgsProcessingOutputBoolean # pylint: disable=ungrouped-imports except ImportError: QgsProcessingOutputBoolean = None

class LyrToQml(SlyrAlgorithm): """ Converts .lyr to QML """

INPUT = 'INPUT'
OUTPUT = 'OUTPUT'
CONVERTED = 'CONVERTED'
ERROR = 'ERROR'

# pylint: disable=missing-docstring,unused-argument

def createInstance(self):
    return LyrToQml()

def name(self):
    return 'lyrtoqml'

def displayName(self):
    return 'Convert LYR to QML'

def shortDescription(self):
    return 'Converts an ESRI LYR file to a QGIS QML file (or files)'

def group(self):
    return 'LYR datasets'

def groupId(self):
    return 'lyr'

def shortHelpString(self):
    return "Converts an ESRI LYR file to a QGIS QML file. If multiple layers are present in the LYR file, each will be converted to an individual QML file."

def initAlgorithm(self, config=None):
    self.addParameter(QgsProcessingParameterFile(
        self.INPUT, 'Input LYR file', extension='lyr'))

    self.addParameter(QgsProcessingParameterFileDestination(
        self.OUTPUT, 'Destination QML file', fileFilter='QML files (*.qml)'))

    if QgsProcessingOutputBoolean is not None:
        self.addOutput(QgsProcessingOutputBoolean(self.CONVERTED, 'Converted'))
    self.addOutput(QgsProcessingOutputString(self.ERROR, 'Error message'))

def processAlgorithm(self,  # pylint: disable=too-many-locals,too-many-statements,too-many-return-statements
                     parameters,
                     context,
                     feedback):
    input_file = self.parameterAsString(parameters, self.INPUT, context)
    output_file = self.parameterAsFileOutput(parameters, self.OUTPUT, context)

    warnings = set()
    with open(input_file, 'rb') as f:
        stream = Stream(f, False, force_layer=True, offset=0)
        try:
            obj = stream.read_object()
        except UnknownClsidException as e:
            feedback.reportError(str(e), fatalError=True)
            return {
                self.ERROR: str(e),
                self.CONVERTED: False,
                self.OUTPUT: None
            }
        except RequiresLicenseException as e:
            raise QgsProcessingException('{} - please see https://north-road.com/slyr/ for details'.format(e)) from e
        except UnreadableSymbolException as e:
            err = 'Unreadable object: {}'.format(e)
            feedback.reportError(err, fatalError=True)
            return {
                self.ERROR: err,
                self.CONVERTED: False,
                self.OUTPUT: None
            }
        except NotImplementedException as e:
            feedback.reportError(str(e), fatalError=True)
            return {
                self.ERROR: str(e),
                self.CONVERTED: False,
                self.OUTPUT: None
            }
        except UnicodeDecodeError as e:
            err = 'Unreadable object: {}'.format(e)
            feedback.reportError(err, fatalError=True)
            return {
                self.ERROR: err,
                self.CONVERTED: False,
                self.OUTPUT: None
            }

    if not LayerConverter.is_layer(obj) and not isinstance(obj, GroupLayer):
        err = 'Objects of type {} are not supported'.format(obj.__class__.__name__)
        feedback.reportError(err,
                             fatalError=False)
        return {
            self.ERROR: err,
            self.CONVERTED: False,
            self.OUTPUT: None
        }

    def on_error(error):
        feedback.reportError(error, fatalError=False)

    def unsupported_object_callback(msg, level=Context.WARNING):
        if msg in warnings:
            return

        warnings.add(msg)
        if level == Context.WARNING:
            feedback.reportError('Warning: {}'.format(msg), False)
        elif level == Context.CRITICAL:
            feedback.reportError(msg, False)

    context = Context()
    context.unsupported_object_callback = unsupported_object_callback
    if Qgis.QGIS_VERSION_INT < 30600:
        context.invalid_layer_resolver = GuiUtils.get_valid_mime_uri
    try:
        LayerConverter.layers_to_qml(obj, input_file, output_file, on_error=on_error, context=context)
    except NotImplementedException as e:
        feedback.reportError(str(e), fatalError=True)
        return {
            self.ERROR: str(e),
            self.CONVERTED: False,
            self.OUTPUT: None
        }

    return {
        self.OUTPUT: output_file,
        self.ERROR: None,
        self.CONVERTED: True
    }

# pylint: enable=missing-docstring,unused-argument

My knowledge of Python code is pretty limited.

PolyGeo
  • 65,136
  • 29
  • 109
  • 338
Joseph
  • 1

1 Answers1

1

You're missing a lot of the required environment setup which is needed to import the qgis modules. Depending on the platform this will differ -- see eg Using Plugin in standalone PyQGIS script

A more straightforward approach would be to use the command line qgis_process application to run the tool -- that involves no Python knowledge and will be considerable easier to get working.

ndawson
  • 27,620
  • 3
  • 61
  • 85