I am trying to load a QGIS vector layer from a SHP file in Python. Whenever I run it, layer.isValid() always returns False (or "Layer is not valid!" in this case). I'm not sure what I am doing wrong here, or if I have instantiated the QgsVectorLayer variable incorrectly.
import sys
import os
from qgis.core import *
import matplotlib.pyplot as plt
from matplotlib.path import Path
import matplotlib.patches as patches
QgsApplication.setPrefixPath("/usr", True)
qgs = QgsApplication(sys.argv, False)
qgs.initQgis()
layer=QgsVectorLayer("/Users/ANON/Desktop/MassShapeFiles/MassachusettsTownBoundaries.shp", "MassachusettsTownBoundaries", "ogr")
providers = QgsProviderRegistry.instance().providerList()
for provider in providers:
print provider
if not layer.isValid():
print "Layer failed to load!"
provider = layer.dataProvider()
Thank you!
I think your path is malformed.
Looking to path structure I assume you are in a windows system, so your windows path should be:
"\\Users\\ANON\\Desktop\\MassShapeFiles\\MassachusettsTownBoundaries.shp"
with double backslash notation to avoid python misunderstandings
you are in windows system. but you have used qgis prefix path as linux system. Get the proper qgis prefix path from qgis python console by printing QgsApplication.showSettings.
Related
when I run this code on jupyter notebook its showing an error.I have already installed graphviz and checked whether its properly installed or not(through this code I have tried to get the decision tree).But when I run this code its saying that,
InvocationException: Program terminated with status: 1. stderr follows: 'C:\Users\Dilki' is not recognized as an internal or external command,
operable program or batch file.
Actually this path is wrong .The actual path is 'C:\Users\Dilki Thishaka'.I couldn't be able to rename the folder name(without the space) since this folder is the administrator folder.How can I fix this.Please help..
#Generate the decision tree
from six import StringIO
from IPython.display import Image
from sklearn.tree import export_graphviz
import pydotplus
dot_data = StringIO()
tree = rnd_clf.estimators_[1]
export_graphviz(tree, out_file=dot_data,feature_names = feature_list,rounded = True, precision = 1)
graph = pydotplus.graph_from_dot_data(dot_data.getvalue())
Image(graph.create_png())
Here is the code and the error
This is a known issue with pydot on Windows.
The below fix steps are from this issue.
1. Find dot.bat file in env. E.g. at C:\Users\Ryan S\.conda\envs\week3\Library\bin\dot.bat
The original file will contain
%~dp0.\graphviz\dot.exe %*
2. Add quotes:
"%~dp0.\graphviz\dot.exe" %*
and save
Feel free to check the issue linked above and this issue too, for more info.
EDIT: Finding the environment
You can find your environment location by running:
import sys
print(sys.prefix)
This will return something like: C:\...\ENV_NAME.
Then dot.bat should be in C:\...\ENV_NAME\Library\bin\dot.bat
I want to set the path of the python script as the working directory. I've tried the solutions I've found other solutions, but they aren't working for me.
This solution:
import os
path = os.path.dirname(os.path.realpath(sys.argv[0]))
dn = os.path.dirname(os.path.realpath("__file__"))
dn
gives:
'C:\\Users\\23392\\Desktop'
and my script is in a folder of desktop.
This solution:
import os
print(os.path.dirname(os.path.realpath(__file__)))
gives the following error:
NameError: name '__file__' is not defined
I need to define it as a string to prevent the error. And I get the same result that the previous one:
'C:\\Users\\23392\\Desktop'
The path should be:
C:\Users\23392\Desktop\05_Work\test.py
EDIT
I've found a partial solution. If I open the file with right click->open with->Atom, it recognizes the path of the file. It works this way but it has to be another way to do it.
Please try this version:
import os
abspath = os.path.abspath(__file__)
basename = os.path.basename(__file__)
fullpath = os.path.join(abspath + "\\" + basename)
print(fullpath)
Write this code into a file and then run it using Python interpreter.
If you try it from an interactive shell it will not work, __file__ is not defined in the interactive interpreter because it is meaningless there.
It is set by the import implementation, so if you use a non-standard import mechanism it might also be unset.
I am writing a command line tool using the Click Python Package:
http://click.pocoo.org/5/
Which is quite usefull but I can't get one issue fixed with that, which is when I enter non ASCII chars as parameter for my Command Line Tool, it will always give me that encoding error:
And yeah I know about encode() and decode() in python, but as you can see in my code I am not touching this string anywhere.
Is it the fault of my console? Am I missing any settings here? I am using Windows 7 cmd.exe and know that Windows likes his own encoding for filenames etc. Do I have to use another console? Tried python one with same result.
The click Documentation states all strings are treated as Unicode...
I would appreciate your help really much.
Installing click is as easy as pip install click
Kind regards,
Marcurion
My Code:
import click
from click_shell import shell
import os
#shell(prompt='Tool > ', intro='some test...', hist_file=os.path.dirname(os.path.realpath(__file__)))
def stRec():
pass
#stRec.command()
#click.argument('name', required=True, type=click.STRING)
def set(name):
print "nothing"
if __name__ == '__main__':
stRec()
I found it out, had to add this on top of the other import statements (all lines are important):
#!/usr/bin/python -S
import sys
reload(sys)
sys.setdefaultencoding("cp1252")
import site
cp1252 is the encoding reported to me by
import locale
print locale.getpreferredencoding()
However the encoding of my "name" parameter was not cp1252 when I got it, had to find out with chardet lib (pip install chardet)that it was actually ISO-8859-9. So since I wanted to create a folder with this argument I encoded it back to cp1252:
#!/usr/bin/python -S
import sys
reload(sys)
sys.setdefaultencoding("cp1252")
import site
import click
from click_shell import shell
import os
import locale
import chardet
#shell(prompt='Tool > ', intro='some test...', hist_file=os.path.dirname(os.path.realpath(__file__)))
def stRec():
pass
#stRec.command()
#click.argument('name', required=True, type=click.STRING)
def set(name):
# Create folder in the folder running this script
folderPath = os.path.join(os.path.split(os.path.abspath(__file__))[0], name)
folderPath = folderPath.decode(str(chardet.detect(bytes(folderPath))['encoding'])).encode(locale.getpreferredencoding())
if not os.path.exists(folderPath):
os.makedirs(folderPath)
if __name__ == '__main__':
stRec()
I want to use NumPy in a Python script that uses pandas to process an Excel file. However, one of my constraints is that my file must be named keyword.py, which causes an import error. The import error is traced back to a line from keyword import iskeyword as _iskeyword in C:\Python27\lib\collections.py, which I assume causes an error because my own keyword.py is overriding the default keyword module. Is there any way to avoid this collision?
Not pretty, but a keyword.py of
if True:
import imp, sys
keyword_loc = imp.find_module("keyword", sys.path[1:])[1]
imp.load_source("keyword", keyword_loc)
import collections
print(collections.Counter)
fails with an AttributeError if we replace True with False, but gives me
(2.7) dsm#notebook:~/coding/kw$ python keyword.py
<class 'collections.Counter'>
as is. This works by finding out where the original keyword library is and manually importing it. After this, any following attempts to import keyword will see that it's already there.
For working with a single script, you can remove the current directory from the import search path. That might be sufficient for working on your TopCoder problem, but I wouldn't recommend it as a long-term solution. (Long-term: don't use file names that mirror the standard library.)
If the following script is called keyword.py, it can be run and the import of collections will not trigger an error.
# keyword.py
# Remove the current directory from the import search path
# This is a hack, but it will be sufficient for working with a
# single script that doesn't import any other modules from the
# current directory.
import sys
sys.path = sys.path[1:]
import collections
print(collections)
I am using OpenCV for various object detectors, and I am finding it difficult to write portable code.
For instance, to load a face detector, on a mac with OpenCV installed via homebrew, I have to write:
haar=cv.Load('/usr/local/Cellar/opencv/2.4.2/share/OpenCV/haarcascades/haarcascade_frontalface_default.xml')
This is not portable; if I wish to change to another machine I'll have to determine another absolute path and change this code.
Is there a variable that holds the OpenCV root for OpenCV? That way I could write something like:
haar=cv.Load(os.path.join(OpenCVRoot, "haarcascades",
"haarcascade_frontalface_default.xml"))
UPDATE: It looks like this is not just a problem for me; it is also a problem for the OpenCV documentation. The documentation contains the following broken example code:
>>> import cv
>>> image = cv.LoadImageM("lena.jpg", cv.CV_LOAD_IMAGE_GRAYSCALE)
>>> cascade = cv.Load("../../data/haarcascades/haarcascade_frontalface_alt.xml")
>>> print cv.HaarDetectObjects(image, cascade, cv.CreateMemStorage(0), 1.2, 2, 0, (20, 20))
[((217, 203, 169, 169), 24)]
This would be simple to avoid if there was a way to infer where examples like lena.jpg and the pre-trained classifiers were installed.
Source: http://opencv.willowgarage.com/documentation/python/objdetect_cascade_classification.html (Retrieved 3/5/13)
You can use cv2.__file__ to get path to the module and then use os.path to resolve symlinks and do some path manipulation. This line of code returns the directory of the haarcascades files on my Mac OS homebrew installation. It may work on other installations too.
from os.path import realpath, normpath
normpath(realpath(cv2.__file__) + '../../../../../share/OpenCV/haarcascades')
It seems there is little hope of having a single mechanism which would be portable across time and space (versions and platforms/environments), but there is some progress - I don't know which version introduced it, but 4.0 has it:
cv2.data.haarcascades - string pointing to a directory, e.g.:
>>> import cv2
>>> cv2.data
<module 'cv2.data' from 'C:\\Users\\USERNAME\\Anaconda3\\envs\\py36\\lib\\site-packages\\cv2\\data\\__init__.py'>
>>> cv2.data.haarcascades
'C:\\Users\\USERNAME\\Anaconda3\\envs\\py36\\lib\\site-packages\\cv2\\data\\'
>>> cv2.__version__
'4.0.0'
But unfortunately, for 3.2.x and 3.4.x there is no such module...
So you could do:
if hasattr(cv2, 'data'):
print('Cascades are here:', cv2.data.haarcascades)
else:
print('This may not work:')
print(normpath(realpath(cv2.__file__) + '../../../../../share/OpenCV/haarcascades'))
check this link
You can use sys.platform to determine the platform and set a different default path depending on the return from sys.platform
I'm in the same boat, and it is an annoying boat.
One convention you can use to deal with such portability issues is use configuration files. In your case, you could have a file ~/.myprojectrc, which could contain:
[cv]
cvroot = '/usr/local/Cellar/opencv/2.4.2/share/OpenCV/`
Files in this format can be read by ConfigParser objects, which should go something like:
import ConfigParser
import os
CONFIG = ConfigParser.ConfigParser()
config_path = os.path.join(os.path.expanduser('~'), '.myprojectrc')
if not os.path.exists(config_path):
raise Exception('You need to make a "~/.myprojectrc" file with your cv path or something')
CONFIG.read(config_path)
...
cv_root = CONFIG.get('cv', 'cvroot')
Then at least when someone uses the code on another machine they don't have to modify any code, they just need to create the config file with the opencv path, and they get a clear error message telling them to do so.
Why don't just copy that folder containing the xml files to your local workspace folder and use the relative path? As I remember, it does not cost much space on your hard drive