[GIS] Creating new empty memory layer with fields scheme from other layer in QGIS

memory-layerpyqgisvector

Being new with python so far, I got inspired by this answer: https://gis.stackexchange.com/a/155988/8202
to dive into it a bit.

When creating features in a new target layer from an existing source layer, all "solutions" I found so far to create that new layer, were to either

  1. prepare the new target layer manually in QGIS beforehand, adding all fields (with field types, lengths etc).
  2. Hard-code the field settings into the python script when creating that new target layer.
    How to create a new empty vector layer programmatically?

It seems a bit odd to me that there should be no programmatic way to clone the attribute scheme of a layer, and create a new (memory) layer with this scheme, so you wont have to change your script for each new layer, or fumble things together manually.

I'm focused on the creation of memory-layers, cause I want to have the opportunity to decide by myself if the outcome is satisfactory and save it manually when it fits my needs.

Best Answer

Here's some quick-and-dirty Python code that works on a simple shapefile layer:

# Get the currently selected layer
inLayer = iface.activeLayer()

# Get its list of fields
inFields = inLayer.dataProvider().fields()

# Convert its geometry type enum to a string we can pass to
# QgsVectorLayer's constructor
inLayerGeometryType = ['Point','Line','Polygon'][inLayer.geometryType()]

# Convert its CRS to a string we can pass to QgsVectorLayer's constructor
inLayerCRS = inLayer.crs().authid()

# Make the output layer
outLayer = QgsVectorLayer(inLayerGeometryType + '?crs='+inLayerCRS, \
    inLayer.name() + u'_copy', \
    'memory')

# Copy the fields from the old layer into the new layer
outLayer.startEditing()
outLayer.dataProvider().addAttributes(inFields.toList())
outLayer.commitChanges()

# Add it to the map
QgsMapLayerRegistry.instance().addMapLayer(outLayer)

I load up a simple shape file, select that layer in the Layers box, paste the above code into the Python console, and a new layer appears with the same attributes.

The key parts here (I'm guessing from your question) are the lines that get the list of fields from the input layer (inLayer.dataProvider().fields(), documented here) and add those same fields to the output layer (outLayer.dataProvider().addAttributes(inFields.toList()), documented here)