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.
    Commented May 23, 2017 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
    Commented May 25, 2017 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.
    Commented May 26, 2017 at 11:53
  • Very strange issue, try replacing your '@layer_name' expression with this expression (note the triple quotes): """ replace(@layer_name,'.shp','') """
    – Joseph
    Commented May 26, 2017 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.
    Commented May 27, 2017 at 10:43

1 Answer 1

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.
    Commented May 23, 2017 at 11:13
  • @T.K. - Are you copying/pasting the code directly into your python console or into a text editor first?
    – Joseph
    Commented May 23, 2017 at 11:17
  • Directly into my Python console, while changing the individual details (path names).
    – T. K.
    Commented May 23, 2017 at 11:19
  • @T.K. Please do not post additional questions as comments
    – Vince
    Commented May 23, 2017 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
    Commented May 23, 2017 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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