Python: script to import multiple LANDSAT images to Grass GIS - python

I'm trying to write a Python code that will import LANDSAT satellite images into Grass GIS by adapting this code: http://grass.osgeo.org/wiki/LANDSAT
LANDSAT tiles are downloaded as folders, each containing 7 tiff images (Band 1-7). I therefore have a directory which contains several subdirectories (one for each LANDSAT tile).
My code at present is as follows:
#!/usr/bin/python
import os
import sys
import glob
import grass.script as grass
def import_tifs(dirpath):
for dirpath, dirname, filenames in os.walk(dirpath):
for dirname in dirpath:
dirname = os.path.join(dirpath,dirname)
for file in os.listdir(dirname):
if os.path.splitext(file)[-1] != '.TIF':
continue
ffile = os.path.join(dirname, file)
name = os.path.splitext(file)[0].split(dirname)[-1]
grass.message('Importing %s -> %s#%s...' % (file, name, dirpath))
grass.run_command('r.in.gdal',
flags = 'o',
input = ffile,
output = name,
quiet = True,
overwrite = True)
def main():
if len(sys.argv) == 1:
for directory in filter(os.path.isdir, os.listdir(os.getcwd())):
import_tifs(directory)
else:
import_tifs(sys.argv[1])
if __name__ == "__main__":
main()
I'm getting the following error:
Traceback (most recent call last):
File "C:/Users/Simon/Documents/import_landsat2.py", line
40, in <module>
main()
File "C:/Users/Simon/Documents/import_landsat2.py", line
37, in main
import_tifs(sys.argv[1])
File "C:/Users/Simon/Documents/import_landsat2.py", line
17, in import_tifs
for file in os.listdir(dirname):
WindowsError: [Error 3] The system cannot find the path
specified: 'dirpath\\C/*.*'
Can anyone explain what is happening and what I need to do to fix it, or suggest an alternative? Thanks.

I believe your main problem is that dirname in os.walk() returns a list (not a string), so your subsequent strings (namely dirname = os.path.join(dirpath,dirname)) are a bit malformed. Here is one possible alternative - to test this, I used the full path to the directory as sys.argv[1], but you can make it more dynamic to suit your case. Also, avoid using variable names such as file since they are Python keywords. I couldn't test out your grass.* functions, but hopefully this will be a clear enough example so you can tweak how you need. os.walk() natively handles a lot of standard parsing, so you can remove some of the directory-manipulating functions:
def import_tifs(dirpath):
for dirpath, dirname, filenames in os.walk(dirpath):
# Iterate through the files in the current dir returned by walk()
for tif_file in filenames:
# If the suffix is '.TIF', process
if tif_file.upper().endswith('.tif'):
# This will contain the full path to your file
full_path = os.path.join(dirpath, tif_file)
# tif_file will already contain the name, so you can call from here
grass.message('Importing %s -> %s#%s...' % (full_path, tif_file, dirpath))
grass.run_command('r.in.gdal',
flags = 'o',
input = full_path,
output = tif_file,
quiet = True,
overwrite = True)

I've just rewritten your code to list all the dir tree and find for a file extension, in this case '.tif',
#!/usr/bin/python
import os
import sys
def import_tifs(dirpath):
for dirpath, dirname, filenames in os.walk(dirpath):
for filename in filenames:
name, extension = os.path.splitext(filename)
if extension.lower() == ".tif":
filepath = os.path.join(dirpath, filename)
print(filepath, name, dirpath)
def main():
if len(sys.argv) == 1:
import_tifs(os.getcwd())
else:
import_tifs(sys.argv[1])
if __name__ == "__main__":
main()
please check if that is what you are looking for...

Related

how can i get the path plus the name of the first file in a folder and so on in python

I got this code and i need to take the first path of a file and the files name an have put it as a string
from pathlib import Path
from os import walk
import os
from posixpath import dirname
f = []
jhon = r'C:\Users\ioshu\Desktop\you'
for (dirpath, dirnames, filenames) in walk(jhon):
f.extend(filenames)
f.extend(dirnames)
break
Ben1= filenames[:1]
Ben2= dirpath[:2]
dataFolder = Path(r'C:\Users\ioshu\Desktop\you')
print(Ben1 , dataFolder)
print(dataFolder)
The print (ben1, dataFolder)
the output" of that file is
C:\Users\ioshu\Desktop\you ['07a5iya4vfm91-DASH_720.mp4']
The problem is that i need the out put to be like this C:\Users\ioshu\Desktop\you\0q74nqluycm91-DASH_720
Using walk will walk the whole tree, which is overkill for your needs. You can simply
first_file_name = os.listdir('/etc')[0]
if you are sure there are only files, or:
import os
path = '/etc' # any path you want
first_file = None
for i in os.listdir(path):
file_path = os.path.join(path, i)
if os.path.isfile(file_path):
first_file = file_path
break # assuming you don't need to sort the names
Always use os.path.join to join paths, works on Linux, Windows, MacOS and any other supported platform.
PS: Ben1 = filenames[:1] returns a list with one element, not the element. If you need the element then: Ben1 = filenames[0].
PS2: If you want to use pathlib then dataFolder / filenames[0] or something will help.

Python Script Saving/Copying into specific directory

I'm attempting to write a script that will save a file in the given directory, but I'm getting a NotADirecotryError[WinError 267] whenever I run it. Any ideas or tips on what I may have done incorrectly?
import shutil
import os
src = 'C:\\Users\\SpecificUsername\\Pictures\\test.txt\'
dest = 'C:\\Users\\SpecificUsername\\Desktop'
files = os.listdir(src)
for file in files:
shutil.copy(file, dest)
for file in files:
if os.path.isfile(file):
shutil.copy(file,dest) ```
There are a couple of things going on here:
You can just use forward slashes in the paths.
Your src is the test.txt file, and not a directory, so you cannot iterate over it using os.listdir().
You can also merge the two loops together since they are looping over the same set of data.
shutil.copy() takes a file path as input, while what you are passing is a filename.
The following code should work and it also copies directories as is:
import shutil
import os
basepath = "C:/Users/SpecificUsername/"
src = "Pictures/"
dest = "Desktop/"
files = os.listdir(os.path.join(basepath, src))
for filename in files:
filepath = os.path.join(basepath, src, filename)
if (os.path.isfile(filepath)):
print("File: " + filename)
shutil.copy(filepath,dest)
else:
print("Dir: " + filename)
shutil.copytree(filepath, os.path.join(dest, filename))
Hope it helps!

files not deletes when using os module

I tried to make a program which delete all of the empty files ( whose size is zero ). Then, i run the program by dragging the script file in "command prompt" and run it .
However, no empty files had deleted (but i have some of them).
Please help me to find the error in my code.
import os
a = os.listdir('C:\\Python27')
for folder in a :
sizes = os.stat('C:\\Python27')
b = sizes.st_size
s = folder
if b == 0 :
remove('C:\\Python27\s')
You're assigning the values iterator os.listdir returns to folder and yet you aren't using it at all in os.stat or os.remove, but instead you are passing to them fixed values that you don't need.
You should do something like this:
import os
dir = 'C:\\Python27'
for file_name in os.listdir(dir):
file_path = os.path.join(dir, file_name)
if os.stat(file_path).st_size == 0:
os.remove(file_path)
You can delete something like the following code and you need to add some exception handling. I have used a test folder name to demonstrate.
import os
import sys
dir = 'c:/temp/testfolder'
for root, dirs, files in os.walk(dir):
for file in files:
fname = os.path.join(root, file)
try:
if os.path.getsize(fname) == 0:
print("Removing file %s" %(fname))
os.remove(fname)
except:
print("error: unable to remove 0 byte file")
raise

command line arguments using python

I have this code that will let the user choose which file he wants to update by passing an argument in the command line, and then it do some more things but I have not included that here:
import sys
import os
from sys import argv
path = "/home/Desktop/python/test"
files = os.walk( path )
filename = argv[1]
if filename in files:
inputFile = open(filename, 'r')
else:
print "no match found"
sys.exit()
inputFile.close()
When I run the script it keeps giving me "no match found" but im pretty sure the file is there. I cant see what Im doing wrong
os.walk() returns a generator, one that produces tuples with (root, directories, files) values for each iteration.
You can't use that generator to test for a single file, not with a simple in membership test.
You'll also need to re-instate the whole path; you can't just open an unclassified filename without the directory it lives in. Just use a for loop here, and break once you found it. The else suite on a for loop only executes when you did not use break (e.g. the file was not found):
path = "/home/Desktop/python/test"
filename = argv[1]
for root, directories, files in os.walk(path):
if filename in files:
full_path = os.path.join(root, filename)
break
else:
print "no match found"
sys.exit()
with open(full_path) as input_file:
# do something with the file
I added a with statement to handle the lifetime of the file object; once the with block is exited the file is automatically closed for you.
Alternatively, you may use following code snippet.
import os.path
filename = argv[1]
path = "/home/Desktop/python/test/"
if os.path.isfile(path + filename):
inputFile = open(path + filename, "r")
else:
print "File Not Found"

How do I create a zip file of a file path using Python, including empty directories?

I've been trying to use the zipfile and shutil.make_archive modules to recursively create a zip file of a directory. Both modules work great--except empty directories do not get added to the archive. Empty directories containing other empty directories are also silently skipped.
I can use 7Zip to create an archive of the same path and empty directories are preserved. Therefore I know this is possible within the file format itself. I just don't know how to do it within Python. Any ideas? Thanks!
There is a example using zipfile:
import os, zipfile
from os.path import join
def zipfolder(foldername, filename, includeEmptyDIr=True):
empty_dirs = []
zip = zipfile.ZipFile(filename, 'w', zipfile.ZIP_DEFLATED)
for root, dirs, files in os.walk(foldername):
empty_dirs.extend([dir for dir in dirs if os.listdir(join(root, dir)) == []])
for name in files:
zip.write(join(root ,name))
if includeEmptyDIr:
for dir in empty_dirs:
zif = zipfile.ZipInfo(join(root, dir) + "/")
zip.writestr(zif, "")
empty_dirs = []
zip.close()
if __name__ == "__main__":
zipfolder('test1/noname/', 'zip.zip')
You'll need to register a new archive format to do that, since the default ZIP archiver does not support that. Take a look at the meat of the existing ZIP archiver. Make your own archiver that creates directories using that currently-unused dirpath variable. I looked for how to create an empty directory and found this:
zip.writestr(zipfile.ZipInfo('empty/'), '')
With that, you should be able to write the necessary code to make it archive empty directories.
This is lifted from Adding folders to a zip file using python but is the only function I have tried that works. The one listed as the answer does not work under Python 2.7.3 (doesn't copy empty directories and is inefficient). The following is tried and tested:
#!/usr/bin/python
import os
import zipfile
def zipdir(dirPath=None, zipFilePath=None, includeDirInZip=True):
if not zipFilePath:
zipFilePath = dirPath + ".zip"
if not os.path.isdir(dirPath):
raise OSError("dirPath argument must point to a directory. "
"'%s' does not." % dirPath)
parentDir, dirToZip = os.path.split(dirPath)
#Little nested function to prepare the proper archive path
def trimPath(path):
archivePath = path.replace(parentDir, "", 1)
if parentDir:
archivePath = archivePath.replace(os.path.sep, "", 1)
if not includeDirInZip:
archivePath = archivePath.replace(dirToZip + os.path.sep, "", 1)
return os.path.normcase(archivePath)
outFile = zipfile.ZipFile(zipFilePath, "w",
compression=zipfile.ZIP_DEFLATED)
for (archiveDirPath, dirNames, fileNames) in os.walk(dirPath):
for fileName in fileNames:
filePath = os.path.join(archiveDirPath, fileName)
outFile.write(filePath, trimPath(filePath))
#Make sure we get empty directories as well
if not fileNames and not dirNames:
zipInfo = zipfile.ZipInfo(trimPath(archiveDirPath) + "/")
#some web sites suggest doing
#zipInfo.external_attr = 16
#or
#zipInfo.external_attr = 48
#Here to allow for inserting an empty directory. Still TBD/TODO.
outFile.writestr(zipInfo, "")
outFile.close()
def zip_dir(src_dir, dst_zip, *, skip_suffixes=None, dry=False):
import logging
from pathlib import Path
from os import walk
from tempfile import TemporaryDirectory
from zipfile import ZipFile, ZipInfo
_log = logging.getLogger(zip_dir.__name__)
_log.addHandler(logging.NullHandler())
_sep = 50 * "-"
skip_suffixes = skip_suffixes or []
src_dir, dst_zip = Path(src_dir), Path(dst_zip)
_log.info("zipping dir: '%s' to: '%s", str(src_dir), str(dst_zip))
if not src_dir.exists():
raise FileNotFoundError(str(src_dir))
if not src_dir.is_dir():
raise NotADirectoryError(str(src_dir))
if dst_zip.exists():
raise FileExistsError(str(dst_zip))
with TemporaryDirectory() as tmp_dir:
tmp_zip_path = Path(tmp_dir).joinpath(dst_zip.name)
with ZipFile(str(tmp_zip_path), mode="w") as zip_out:
for root, dirs, files in walk(src_dir):
root = Path(root)
for folder in dirs:
folder = root.joinpath(folder)
# add empty folders to the zip
if not list(folder.iterdir()):
_log.debug(_sep)
folder_name = f"{str(folder.relative_to(src_dir))}/"
_log.debug("empty dir: '%s'", folder_name)
if dry:
continue
zip_out.writestr(ZipInfo(folder_name), "")
for file in files:
file = root.joinpath(file)
_log.debug(_sep)
_log.debug("adding: '%s'", str(file))
should_skip = None
for suffix in file.suffixes:
if suffix in skip_suffixes:
should_skip = suffix
break
if should_skip:
_log.debug("skipped [%s]: %s", should_skip, str(file))
continue
arcname = str(file.relative_to(src_dir))
_log.debug("arcname: '%s'", arcname)
if dry:
continue
zip_out.write(str(file), arcname=arcname)
if not dry:
dst_zip.write_bytes(tmp_zip_path.read_bytes())
tmp_zip_path.unlink()
if __name__ == '__main__':
import logging
logging.basicConfig(level=logging.DEBUG, format="%(asctime)s | %(levelname)8s | %(module)25s:%(lineno)-5s | %(message)s")
zip_dir("/tmp/opera_profile", "opera_profile.zip", skip_suffixes=[".log"], dry=True)

Categories

Resources