2

The task I would like to solve is to write an individual shapefile's name into a new column of its attribute table for all shapefiles in a given directory.

My current - disfunctional - code looks like this:

import glob, os, processing
input_path = "/home/me/Folder/"
for layer in glob.glob(input_path + "*.shp"):
   processing.runalg("qgis:fieldcalculator", layer, 'columnname', 2, 25.0, 3.0, True, '@layer_name', os.path.basename(layer) + *_new.shp")

This results, so far, in an indentation error pointing to the last element of the algorithm's elements.


Using Joseph's code provided below (copied from a text editor into the Python console), the algorithm runs over one shapefile, writes the shapefile's name including the .shp-ending into a column, then ends abruptly with the following error:

Traceback (most recent call last):
  File "<input>", line 3, in <module>
  File "/usr/share/qgis/python/plugins/processing/tools/general.py", line 75, in runalg
    alg = Processing.runAlgorithm(algOrName, None, *args, **kwargs)
  File "/usr/share/qgis/python/plugins/processing/core/Processing.py", line 257, in runAlgorithm
    if not param.setValue(args[i]):
  File "/usr/share/qgis/python/plugins/processing/core/parameters.py", line 997, in setValue
    self.value = unicode(obj)
UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 88: ordinal not in range(128)

The names to be written contain German Umlaute, could this cause any problems of this kind?


After removing the Umlaute, I ran this code:

import glob, os, processing
input_path = "/Some/Folder/"
for layer in glob.glob(input_path + "*.shp"):
    output = "/Some/Folder/Subfolder/" + os.path.splitext(os.path.basename(layer))[0] + "_withName.shp"
    processing.runalg("qgis:fieldcalculator", layer, 'Name', 2, 25.0, 0, 1,  '@layer_name', output)

The result is almost as it should be except for the layers' names written into the attribute table still having the .shp-ending. What's wrong with the field calculator command here?


Following Joseph's advice, the code that eventually did the trick was:

import glob, os, processing
input_path = "/Some/Folder/"
for layer in glob.glob(input_path + "*.shp"):
    output = "/Some/Folder/Subfolder/" + os.path.splitext(os.path.basename(layer))[0] + "_withName.shp"
    processing.runalg("qgis:fieldcalculator", layer, 'Name', 2, 25.0, 0, 1,  """ replace(@layer_name,'.shp','') """, output)

As far as I can tell, the replace-command works like this: replace(@layer_name, 'bit to be replace', 'bit to replace it with') - but what exactly are the triple quotes for, Joseph?

6
  • See original post, sorry for the omission.
    – T. K.
    May 23 '17 at 10:49
  • Can you please clarify what you mean by "the saved names still having the .shp-ending". All files have this ending? Can you give an example of an output filename?
    – Joseph
    May 25 '17 at 10:56
  • Now that I re-read my question, I formulated it unclearly. What I actually meant was that the layer's name written as an attribute into the newly-created column still contained said ending. Therefore, the question is how to tweak the field calculator's action in order to write Name into the attribute table instead of Name.shp.
    – T. K.
    May 26 '17 at 11:53
  • Very strange issue, try replacing your '@layer_name' expression with this expression (note the triple quotes): """ replace(@layer_name,'.shp','') """
    – Joseph
    May 26 '17 at 13:29
  • This worked, thank you Joseph. If you have the time, please educate me on the function of the triple quotes.
    – T. K.
    May 27 '17 at 10:43
2

Usually when you indent, you use four spaces. Also I think there's a typo in the following line:

os.path.basename(layer) + *_new.shp"

Where you used * instead of ". But this is just giving the output filename. Instead, you need to give it a full path including the new filename.

So you could try using something like the following:

import glob, os, processing
input_path = "/home/me/Folder/"
for layer in glob.glob(input_path + "*.shp"):
    output = input_path + os.path.splitext(os.path.basename(layer))[0] + "_new.shp"
    processing.runalg("qgis:fieldcalculator", layer, 'columnname', 2, 25.0, 3.0, True, '@layer_name', output)

Note that the code above saves the output in the same directory as the input. If you want to change this, replace input_path in the output parameter. E.g:

output = "another/path/" + os.path.splitext(os.path.basename(layer))[0] + "_new.shp"
8
  • Unfortunately, the console gives me another indentation error after entering the first element (output...) of the for-loop in your example. Any idea as to why?
    – T. K.
    May 23 '17 at 11:13
  • @T.K. - Are you copying/pasting the code directly into your python console or into a text editor first?
    – Joseph
    May 23 '17 at 11:17
  • Directly into my Python console, while changing the individual details (path names).
    – T. K.
    May 23 '17 at 11:19
  • @T.K. Please do not post additional questions as comments
    – Vince
    May 23 '17 at 11:21
  • @T.K. - I suggest copying/pasting the above code into a text editor like Notepad, the indentation should still be valid, make the changes to the details, then paste the whole thing into the python console. Otherwise, please edit your question to include your progress so far :)
    – Joseph
    May 23 '17 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.