After loading a vector layer, viewing its attributes is the next logical step.
We previously noted that the addVectorLayer() function returns a QgsVectorLayer object. In this context “returns” means that this function creates an object that we can use. Telling the iface to add a vector layer is similar to telling a restaurant to make you a pizza. If everything works out (whether it’s cooking or object creating), you’ll get a pizza to eat – or a vector layer to continue working with.
We need to give a name to the returned QgsVectorLayer object so that we can refer to it later. We’ll chose to call it vlayer:
uri = "E:/Geodata/NaturalEarth/vector_v4/natural_earth_vector.gpkg_v4.1.0/packages/natural_earth_vector.gpkg|layername=ne_10m_admin_0_countries" vlayer = iface.addVectorLayer(uri, "countries", "ogr")
When we call the addVectorLayer() function, a lot of things happen in the background: QGIS checks the vector layer path and tries to open it using the provider that we specified. If successful, it adds the layer to the project using the name we provided. It also makes sure that the map is redrawn so that we can actually see the new layer on the map. And last but not least, it returns the newly created QgsVectorLayer object so we can use it later.
Now that we have our vlayer object we can do something with it – like opening its attribute table using the iface.showAttributeTable function:
iface.showAttributeTable(vlayer)
Every time we run addVectorLayer(), QGIS creates a new QgsVectorLayer object and adds the layer to the project. If you want to stop a particular piece of code from being executed, you can comment it out by putting a hashtag in front of the code:
uri = "E:/Geodata/NaturalEarth/vector_v4/natural_earth_vector.gpkg_v4.1.0/packages/natural_earth_vector.gpkg|layername=ne_10m_admin_0_countries" #vlayer = iface.addVectorLayer(uri, "countries", "ogr") iface.showAttributeTable(vlayer)
Instead of just opening the attribute table dialog, we can of course use the attributes in code as well. As with the iface object we dealt with earlier, QgsVectorLayer objects have a whole lot of functions (methods). To get a list of the attribute (or field) names printed to the console, we can go through the layer’s fields provided by the fields() function. This function returns a QgsFields object. To print all field names to the console, we can use a for loop:
for field in vlayer.fields(): print(field.name())
You can read these two lines of code as: For each field in the vector layer’s fields, print the field name. In this case, fields() is a function of our vector layer object while field is a variable name that can be chosen freely.
In a similar way, we can print the ADMIN attribute value of our layer’s features using the getFeatures() function:
for feature in vlayer.getFeatures(): print(feature["ADMIN"])
This code is the first example of how Python code is structured by indenting lines of code (i.e. putting spaces or tabs at the beginning of the line). If you omit the spaces before the print function, you’ll see an error. The correct number of spaces (or whether to use spaces or tabs) has been a topic of many discussions. By default, the code editor will insert 4 spaces. It is important to be consistent and avoid mixing different indentation styles. It’s not uncommon to run into errors because tabs were mixed with spaces.
These are the basics of viewing vector layer attribute names and values. You also saw how to write a for loop to iterate through a vector layer’s fields and features.
PyQGIS 101 is a work in progress. I’d appreciate any feedback, particularly from beginners!
My feedback so far would be to add instructions on how to save code after this lesson. I closed QGIS but neglected to save my code, and am now having to recreate it in order to continue with the next lesson.
Good point, thanks! I’ve added a reminder to “Loading a vector layer”.
Probably a stupid question but… i’m beginning.
If you comment the “vlayer = iface.addVectorLayer(uri, “countries”, “ogr”)”
How does the call for vlayer in “iface.showAttributeTable(vlayer)” can possibly work ?
For your understanding i execute your code from a .py file that is like this at the moment:
uri = “D:/MNT/GEOFLA.gpkg|layername=Communes”
#vlayer = iface.addVectorLayer(uri, “COMMUNES”, “ogr”)
for feature in vlayer.getFeatures():
print(feature[“NOM_COMM”])
Thanks !
Hi Chris,
If you run vlayer = iface.addVectorLayer(uri, “countries”, “ogr”) once, QGIS will remember it. You can test it by typing vlayer into the Python console and pressing enter. It should return .
I’ve introduced the possibility of commenting code out in this chapter since QGIS will keep on adding new layers based on the same input dataset if you call addVectorLayer over and over.
Hey ! Thanks for the answer. It makes sense: The variable keep it’s value until you change it or you close your QGIS. Just to be precise (and maniac ?), is it QGIS or Python that “remember” the value ?
It only exists in the context of the Python Console, afaik.
Hi,
I started learning Python in February this year and my main goal has always been to use it in QGIS.
Unfortunately I couldn’t manage to pass the first “for loop” and I get the following error:
“AttributeError: ‘QDialog’ object has no attribute ‘fields'”
Am I doing something wrong?
Thank you.
Hi, I managed! My mistake!
Dear writer, It is helping me a lot..thogh this i am able to add a vector and raster layer successfully. Now please guide me how to clip a raster layer with the help of a shape file,
Thank you for your feedback Amrita. For clipping a raster with a shapefile, consider the Clip Raster by Mask Layer tool in the Processing toolbox. PyQGIS 101: Running Processing tools shows how to run Processing tools from Python. For this tool, it would be something like:
processing.run("gdal:cliprasterbymasklayer", {'INPUT':'D:/Documents/Geodata/NaturalEarthData/50m_raster/NE1_50M_SR_W/NE1_50M_SR_W.tif', 'MASK':'D:/Documents/Geodata/NaturalEarthData/110m_cultural/ne_110m_admin_0_countries.shp', 'NODATA':None, 'ALPHA_BAND':False, 'CROP_TO_CUTLINE':True, 'KEEP_RESOLUTION':False, 'OPTIONS':'', 'DATA_TYPE':5, 'OUTPUT':'C:/temp/OUTPUT.tif'})
Hi Anita, thanks for you tutorials.
I have a question about “for loop”, when I execute script about “field.name()”, it shows all field names, how to write a script to show only 2nd field name or 10th field name. I know it must be simple but I’m a beginner and fail to do it for now.
Hi Siqer,
To directly access the 2nd field name, use:
print(vlayer.fields().at(1).name())
The QgsFields.at() function is documented in https://qgis.org/pyqgis/master/core/other/QgsFields.html?highlight=qgsfields
Thanks for your response Anita,
What you say it works, the same does print(vlayer.fields().field(1).name())
But they show not particularly one field name, but all fields under one name. E.g. if there are 12 fields it will show one name 12 times.
Call the print from outside the loop to avoid it printing multiple times
Yes, it works. Thank you Anita!
Thank You very much Anita for your work and sharing your knowledge :)
With basics of Python I started using it in QGIS with You ;)
Thanks Anita. I am using QGIS 3.6. When I used a backslash in the URL it treated it as an escape character. When I changed it to a forward slash it worked fine. Thanks for getting me started on this.
invalid syntax
i use for field in vlayer.field
It’s:
for field in vlayer.fields():
Hi! Beforehand I would like to appreciate your effort. However, once I run the following code:
uri = “/Users/leonardosanchez/Documents/Subestaciones\ y\ lineas/Full\ line\ layers.shp”
vlayer = iface.addVectorLayer(uri, “countries”, “ogr”)
iface.showAttributeTable(vlayer)
An error message comes up, saying that Layer is not valid: The layer /Users/leonardosanchez/Documents/Subestaciones\ y\ lineas/Full\ line\ layers is not a valid layer and can not be added to the map.
I would really appreciate if you could help to me to solve the problem.
The backslashes probably need to be escaped or you need to use file paths without spaces.
Hi Anita, great work! Just a small typo to correct: after the third block of code there’s a “QqsVectorLayer” instead of “QgsVectorLayer”.
Best,
Ale
Thanks Ale, it’s fixed now.
Thanks for this useful tutorial. I’m just getting started with PyQGS and have a problem when running. The first lines of the code work, the layer is loaded and the attribute table opened. However, there is no output for the loops. The following error occurs:
uri = ‘C:/Natural Earth/countries/ne_10m_admin_0_countries.shp’
vlayer = iface.addVectorLayer(uri, “countries”, “ogr”)
iface.showAttributeTable(vlayer)
for field in vlayer.fields():
print(field.name())
Then, there appears “…” instead of “>>>” in the console window … are you familiar with this type of problem?
Okay. Looks like I always have to run the whole file instead of only running the selected part of the code. Furthermore, I need to put the quotes as ‘ ‘ instead of ” ” …. ready to proceed then…
Hi Anita
These are very good tutorials, nicely put together and easy to follow.
I am trying to iterate through all the attributes to set them to hidden. Your code shows how to display the attribute names, but how can I set the properties of each attribute?
Thanks – Rob
Hi Anita,
Thanks for this wonderful tutorial. I don’t know what am doing wrong but getting this error.
Traceback (most recent call last):
File “C:\PROGRA~1\QGIS3~1.4\apps\Python37\lib\code.py”, line 90, in runcode
exec(code, self.locals)
File “”, line 1, in
File “”, line 6, in
KeyError: ‘ADMIN’
Hi Philip, does your dataset contain a column called ADMIN?
Hi Anita, I get exactly the same error
Oops I worked it out I didn’t have an ADMIN field
Hello Anita, as others have commented, this is a great resource you’ve created.
I am curious as to why some things are functions/methods and not properties.
Coming from the ArcGIS world I can see why in Esri vocabulary, things like field names are properties (field.name) and not methods (field.name()). I think there is a good reason for this to prevent inadvertent data corruption, though this is of course arguable!
So with that in mind could you show a practical example of where one might issue parameters to a field.name() method?
Thanks!
Eric
I think this is an effect of the Python API mirroring the C++ code (https://qgis.org/api/qgsfield_8h_source.html#l00059) but core developers might be able to provide a more in-depth answer.
The first page of this tutorial is awesome, all edges of the topic are well explained and defined, is like a very sharp camera that captured even the smallest detail of the scene… But as the pages unfolds progessively it becomes gradually blurry as if the camera becomes lazy taking every details out of the scene… It is like a heap of straw suddenly burning into flames wirh in a blink of an eye ir loses the fire in a long run, because there is nothing to be burn. It is bored and tired already…
Since the previous tutorial explained how to use the PyQGIS documentation, this tutorial assumes that readers can apply this knowledge.
Please elaborate what getFeatures function is… You don’t have to include strange function without further elaboration what the heck it is…. first to avoid confusion contamination. 😀 Remember that the previous learning is a very significant – rigid foundation for the next topic… Without grasping the necessary requisite for the next, it is like crossing a huge desert having only a few resources that forfeit the entire journey….
Please elaborate what is unclear about the getFeatures function? The term “feature” should be clear to QGIS users.
Hi Anita,
Thank you for the tutorial. Even I am a beginner, I can able to understand your coding and explanation clearly. Great.
Hi Anita, Thank you for your tutorial. I am a beginner. I need to include the output of a “List unique values” as drow-down in the processing modeler in QGIS. Is there an option to link this output as temporary and to display it in the dialog?
how do I loop through the values in a field such that the second value minuses the first and continues to the end?
Dear Biginner, please clarify: does the field contain a list of (comma separated?) values that you want to subtract? from each other?
So the field is from a vector layer attribute table. What I want is to be able to have the result when each row value in the field named “Distance” subtracts from the previous one, I get a result which I can then use for other calculations. So essentially I want to be able to say: row 3 in column 4 minus row 2 in column 4 (same columns but different rows subtracting each other).My code is shown below:
fn = ‘C:/PLUGINS1/sample/checking.shp’
layer = iface.addVectorLayer(fn, ”, ‘ogr’)
layer=iface.activeLayer()
idx=layer.fields().indexFromName(‘Distance’)
with edit(layer):
for f in layer.getFeatures():
dist1 = float(row[2], column [4]) # since row 1 contains the field name
dist2 = float(row[3], column [4])
final = abs(dist2 – dist1)
I will appreciate all practical assistance given. Thanks.
Basically, the “rows” are the same as “features” since every row represents a feature. Therefore, while looping through the features (with the for loop) you need to keep a reference to the previous feature’s attribute value.
Hi Anita, thank you very much for this webpage! I have a question: can you refer to a vector layer already inside the layer browser in your file, or do you always have to refer to it with folder location?
How is it done from a postgis db?
Many thanks!
Hi Felipe, here’s how to refer to an existing layer: https://gis.stackexchange.com/a/136879/187
and here the PostGIS layer: https://gis.stackexchange.com/a/300196/187
for field in vlayer.fields():
print(field.name())
“You can read these two lines of code as: For each field in the vector layer’s fields, print the field name. In this case, fields() is a function of our vector layer object while field is a variable name that can be chosen freely.”
– Choosing freely does not seem to work. Iteration “fails”: It does always lead to the last fieldname and print that for each contained field instead ( always NAME_ZH for the example dataset). Maybe you can/should explain that?
THX in advance!
Gosh! Describing the outcome, I recognize that it is typical: I should avoid typos leading to differences between for loop and print statement. Sorry for that.