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:


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")

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():

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():

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!

  1. bwilkes said:

    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”.

  2. Chris said:

    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():

    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.

      • Chris said:

        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.

  3. Pedro Bittencourt said:


    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.

  4. Pedro Bittencourt said:

    Hi, I managed! My mistake!

  5. Amrita Bandyopadhyay said:

    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:"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'})

  6. siqer said:

    Hi Anita, thanks for you tutorials.

    I have a question about “for loop”, when I execute script about “”, 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.

      • siqer said:

        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

      • siqer said:

        Yes, it works. Thank you Anita!

  7. Agnieszka said:

    Thank You very much Anita for your work and sharing your knowledge :)
    With basics of Python I started using it in QGIS with You ;)

  8. 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.

  9. Veronika said:

    invalid syntax
    i use for field in vlayer.field

  10. leonardo sanchez said:

    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”)

    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.

  11. sale said:

    Hi Anita, great work! Just a small typo to correct: after the third block of code there’s a “QqsVectorLayer” instead of “QgsVectorLayer”.

  12. Philipp said:

    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”)

    for field in vlayer.fields():

    Then, there appears “…” instead of “>>>” in the console window … are you familiar with this type of problem?

    • Philipp said:

      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…

  13. 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

  14. 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\”, 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?

    • John said:

      Hi Anita, I get exactly the same error

      • John said:

        Oops I worked it out I didn’t have an ADMIN field

  15. sova said:

    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 ( and not methods ( 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 method?


  16. Dodem mahapat said:

    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.

  17. Dodem mahapat said:

    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.

  18. krishna said:

    Hi Anita,
    Thank you for the tutorial. Even I am a beginner, I can able to understand your coding and explanation clearly. Great.

  19. Angela Blanco-Vogt said:

    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?

  20. Biginner said:

    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?

      • Beginner said:

        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’)

        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.

  21. felipe said:

    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!

  22. chris said:

    for field in vlayer.fields():

    “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!

    • chris said:

      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.

Leave a Reply to underdark Cancel reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: