Where do I download grass.scripts and/or grass.pygrass? - python

I am trying to learn how to do some scripting to run Grass externally with Python but I can't seem to even find the basic modules called for this type of script. All of the documentation I have seen describes using grass.scripts module but I don't know where to download this. I also saw some information on grass.pygrass but I can't find this either.
I thought that maybe it was builtin to a newer version of Grass so I just downloaded 7.0.0 beta2 and I still find grass.scripts files. Is this a python module like others (matploblib, numpy, scipy etc.) or is it internal to Grass? Sorry for the remedial questions but I am lost here.
I ran the following script (taken from http://grasswiki.osgeo.org/wiki/GRASS_and_Python with quotations added since I run Python 2.7)
GISBASE= 'C:\GRASS-64'
GISRC= 'C:\Documents and Settings\user\.grassrc6'
LD_LIBRARY_PATH= 'C:\GRASS-64\lib'
PATH= 'C:\GRASS-64\etc;C:\GRASS-64\etc\python;C:\GRASS-64\lib;C:\GRASS-64\bin;C:\GRASS-64\extralib;C:\GRASS-64\msys\bin;C:\Python26;'
PYTHONLIB= 'C:\Python26'
PYTHONPATH= 'C:\GRASS-64\etc\python'
GRASS_SH= 'C:\GRASS-64\msys\bin\sh.exe'
and it is fine (though I don't know what it does) but when I add
from grass.pygrass.modules import Module
it returns
ImportError: No module named gras.pygrass.modules
Normally I would download and install the module and the problem would be fixed but I can't find it anywhere.

I ran the following script (taken from http://grasswiki.osgeo.org/wiki/GRASS_and_Python with quotations added since I run Python 2.7)
GISBASE= 'C:\GRASS-64'
GISRC= 'C:\Documents and Settings\user\.grassrc6'
LD_LIBRARY_PATH= 'C:\GRASS-64\lib'
PATH= 'C:\GRASS-64\etc;C:\GRASS-64\etc\python;C:\GRASS-64\lib;C:\GRASS-64\bin;C:\GRASS-64\extralib;C:\GRASS-64\msys\bin;C:\Python26;'
PYTHONLIB= 'C:\Python26'
PYTHONPATH= 'C:\GRASS-64\etc\python'
I don't know why you think Python 2.7 requires you to add quotes. It doesn't.
But it does require you to replace all those Python26 with Python27. And that could easily be your problem. You don't have anything at C:\Python26.
And if you installed Grass somewhere other than C:\GRASS-64 you obviously need to change that as well. (From elsewhere in the file, I get the feeling that 64 refers to version 6.4, not to being 64-bits or something else, and you've downloaded 7.0.0, so I suspect it got installed to something like C:\GRASS-70.)
Or it could be this:
ImportError: No module named gras.pygrass.modules
If you import gras.pygrass.modules instead of grass.pygrass.modules, that's obviously not going to work.
Also, are you actually running that script in the same cmd.exe window that you use to start Python? If not, it's not going to help.
Meanwhile:
All of the documentation I have seen describes using grass.scripts module but I don't know where to download this.
The documentation you linked to answers that question, although it may not be obvious to a novice (once you figure this out, you might want to suggest documentation improvements upstream):
The related files are at $GISBASE/etc/python/grass/script/*.py.
On Windows, of course, that's $GISBASE isn't literally right; it's actually %GISBASE%, which is something like C:\GRASS-64, but it's the same thing. The files are already on your system; there is nothing to download. That's the whole point of setting PYTHONPATH to C:\GRASS-64\etc\python.
Is this a python module like others (matploblib, numpy, scipy etc.) or is it internal to Grass?
Well, it's not exactly "internal to Grass", but it's distributed with Grass, rather than as a separate module.

I'm still not sure I understand everything but I seem to be past this hurdle. I used the script from (https://gis.stackexchange.com/questions/89452/problem-with-python-script-to-control-grass-gis-from-outside-how-to-import-gra/90160#90160) and changed all the relevant path information to suite my installation and apparently, now the grass.script module is accessed. Here is my working script
import os
import sys
gisbase = os.environ['GISBASE'] = 'C:\program files\grass gis 6.4.3' #GISBASE needs to point the root of the GRASS installation directory
gisrc = 'C:\grassdata'
gisdbase = 'C:\grassdata'
location = 'newLocation'
mapset = 'TC'
LD_LIBRARY_PATH = 'C:\program files\grass gis 6.4.3\lib'
PATH = 'C:\program files\grass gis 6.4.3\etc';'C:\program files\grass gis 6.4.3\etc\python';'C:\program files\grass gis 6.4.3\lib';'C:\program files\grass gis 6.4.3\bin';'C:\Python27';'C:\program files\grass gis 6.4.3\Python27';'C:\program files\grass gis 6.4.3\msys'
PYTHONLIB = 'C:\Python27'
PYTHONPATH = 'C:\program files\grass gis 6.4.3\etc\python'
GRASS_SH = 'C:\OSGeo4W64\apps\msys\bin\sh.exe'
sys.path.append(os.path.join(os.environ['GISBASE'], 'etc', 'python'))
import grass.script as grass

Related

How to import .Net Classes in Python using Python.Net

I'm using Python.NET to create wrapper for iText.net (https://github.com/itext/itext7-dotnet).
The dll is named itext.kernel.dll and the python script is in the samne folder of all the itext dlls.
With Jetbrain dotPeek I see that itext.kernel has various namespaces; the namespace iText.Kernel.Pdf is what I need, in particular the public class PdfReader.
Here's what I'm doing (from the docs on https://pythonnet.github.io/):
import clr
clr.AddReference('itext.kernel')
sys.path.append(os.getcwd()) # the script is currently in the dll folder
from iText.Kernel.Pdf import PdfReader
But this gets me a "ModuleNotFoundError: No module named 'iText'" error.
I can't understand what it's wrong, can someone point me to the right direction? Thanks.
edit: I can import and use iTextSharp just fine, it seems iText7 has something different.
Well, long story short I really wanted this to work... and solved my issue!
I tried using older builds, and I found out that build 7.0.8 worked fine.
I compared it with build 7.1.11 (the one I was having problems with) using dotPeek, and noticed it has some references, namely BouncyCastle.Crypto, Common.Logging and Common.Logging.Core.
I did put them in the project folder, but still no dice... until I noticed I was using BouncyCastle.Crypto build 1.8.6, while the itext.kernel referred build 1.8.5! Replacing with that version solved the issue.
Basically the newer builds of iText7 have 3 referenced libs, that must be present in the exact same version (at least to be imoported by pythonnet).
I hope this can help someone that has issues similar to mine.

Is it possible to specify the search path for a module in a python script? If it is, how do I do that?

I have been coding in python for about 2 months, but I'm only familiar with basic object-oriented programming, so I do not really understand things like how searching for modules is implemented. (Basically I'm a noob.)
I pip installed a package called Opentrons Opentrons 2.5.2 and all its dependencies into the samefolder as a python script I'm currently writing. However when I tried to import the module below[1], I get an error saying that "Opentrons is not a module". Then, I tried shifting it into the python library because I found out the search path using the pprint module and it seems to work. I was wondering if I can specify the search path from the .py file itself instead of manually printing the search path and putting the file into the library that the script searches for. (Willing to put in images of the directories I put the opentrons package in if it helps.)
[1]
import sys
import pprint
pprint.pprint(search.path)
from opentrons import robot, containers, instruments
Edit: I realise that the fact that I am running all my scripts in a Spyder console located in a python 3.6 environment might be important.
You can try using the __import__ function, or importlib. This should allow you to specify the path.

Including xlrd/xlwt/xlutils with modules outside of python installation

I'm self-taught in the Python world, so some of the structural conventions are still a little hazy to me. However, I've been getting very close to what I want to accomplish, but just ran into a larger problem.
Basically, I have a directory structure like this, which will sit outside of the normal python installation (this is to be distributed to people who should not have to know what a python installation is, but will have the one that comes standard with ArcGIS):
top_directory/
ArcToolbox.tbx
scripts/
ArcGIStool.py (script for the tool in the .tbx)
pythonmod/
__init__.py
general.py
xlrd/ (copied from my own python installation)
xlwt/ (copied from my own python installation)
xlutils/ (copied from my own python installation)
So, I like this directory structure, because all of the ArcGIStool.py scripts call functions within the pythonmod package (like those within general.py), and all of the general.py functions can call xlrd and xlwt functions with simple "import xlrd" statements. This means that if the user desired, he/she could just move the pythonmod folder to the python site-packages folder, and everything would run fine, even if xlrd/xlwt/xlutils are already installed.
THE PROBLEM:
Everything is great, until I try to use xlutils in general.py. Specifically, I need to "from xlutils.copy import copy". However, this sets off a cascade of import errors. One is that xlutils/copy.py uses "from xlutils.filter import process,XLRDReader,XLWTWriter". I solved this by modifying xlutils/copy.py like this:
try:
from xlutils.filter import process,XLRDReader,XLWTWriter
except ImportError:
from filter import process,XLRDReader,XLWTWriter
I thought this would work fine for other situations, but there are modules in the xlutils package that need to import xlrd. I tried following this advice, but when I use
try:
import xlrd
except ImportError:
import os, sys, imp
path = os.path.dirname(os.path.dirname(sys.argv[0]))
xlrd = imp.load_source("pythonmod.xlrd",os.path.join(path,"xlrd","__init__.py"))
I get a new import error: In xlrd/init.py, the info module is called (from xlrd/info.py), BUT when I use the above code, I get an error saying that the name "info" is not defined.
This leads me to believe that I don't really know what is going on, because I thought that when the init.py file was imported it would run just like normal and look within its containing folder for info.py. This does not seem to be the case, unfortunately.
Thanks for your interest, and any help would be greatly appreciated.
p.s. I don't want to have to modify the path variables, as I have no idea who will be using this toolset, and permissions are likely to be an issue, etc.
I realized I was using imp.load_source incorrectly. The correct syntax for what I wanted to do should have been:
imp.load_source("xlrd",os.path.join(path,"xlrd","__init__.py"))
In the end though, I ended up rewriting my code to not need xlutils at all, because I continued to have import errors that were causing many more problems than were worth dealing with.

Python Throws ImportError: No module named..." Error

I'm trying to install the Chilkat library for Python in order to use its encryption functionality, but being new to Python in every possible way, I'm getting stuck entirely too early. I've installed the library as instructed by the docs and verified that the files are in the "right place" (/usr/local/lib/python2.7/site-packages/) on my Ubuntu 12.04 server.
I've also downloaded the test script. When I try to run it, however:
ImportError: No module named chilkat
I know this is stupid basic, but here I am. In the docs they do mention a possible issue with sys.prefix. That (presumably default, since I've never touched it) value on my machine is /usr. I moved everything there, but still get the same error.
Help? Where is the most "pythonic" place to put these files and how can I get Python to recognize them universally?
Thanks.
For anyone searching, I just ended up adding site-packages to my sys.path by adding a .pth file to dist-packages which was already in my path.
echo "/usr/local/lib/python2.7/site-packages" > /usr/local/lib/python2.7/dist-packages/site-packages.pth

Python for .NET "unable to find assembly" error

I'm using CPython and I have a C# dll. I'm trying to use Python for .NET to make them talk. I can't use IronPython because I need to integrate this into an existing CPython system.
I'm completely new to Python for .NET, and I actually have very little experience with Python and no experience with C#. So please forgive me if my question seems very basic.
I'm using Python 2.7.3, and I downloaded
pythonnet-2.0-alpha2-clr2.0_131_py27_UCS2 and unzipped it into a folder named pyfornet_test, which also contains the dll I'm trying to use (called DotNet4Class.dll)
Then I run this:
import sys
import os
import clr
sys.path.append(r"C:\pyfornet_test")
clr.AddReference("DotNet4Class.dll")
Which gives me this error:
System.IO.FileNotFoundException: Unable to find assembly 'DotNet4Class.dll'.
at Python.Runtime.CLRModule.AddReference(String name) in C:\Users\Barton\Documents\Visual Studio 2008\Projects\PyShar
p\trunk\pythonnet\src\runtime\moduleobject.cs:line 375
Any advice would be much appreciated. Thank you!
One reason can be Windows was not enabling it to load from "external sources". To fix this:
Right-click on the .dll
"Properties"
Under "General", click "Unblock"
Try this (without extension .dll):
clr.AddReference(r"C:\pyfornet_test\DotNet4Class")
Is DotNet4Class.dll built against .NET 4? I assume so based on the naming of the dll.
Note the issue here: http://sourceforge.net/tracker/?func=detail&aid=3293169&group_id=162464&atid=823891
clr.AddReference fails when assembly is built with .NET 4.0 - ID: 3293169
I'd read the solution, but essentially, you need to rebuild and recompile the python for .NET project under .NET 4.
I'll also mention that projects like this, that aren't actively developed and used by lots of people, generally have subtle idiosyncrasies that make knowledge of the platform essential to work around problems such as this. It sounds like you're trying to hack this solution in without understanding much about python or .NET which is always going to be fraught with problems.
Did you try clr.FindAssembly?
import clr
import sys
assemblydir = r"C:\pyfornet_test"
assemblypath = r"C:\pyfornet_test\DotNet4Class.dll"
sys.path.append(assemblydir)
clr.FindAssembly(assemblypath)
I don't know why it works, but this code works on my computer (Python 2.7, .NET4)
I have code like this (I copied MyRightClickMenuService.dll to the same directory as my script.py). It is built against .Net 4.0.
# script.py
import clr
import os
import sys
sys.path.append(os.path.dirname(__file__))
clr.AddReference('MyRightClickMenuService')
clr.AddReference('System')
clr.AddReference('System.Security')
from MyRightClickMenuService import (
AclSecuredNamedPipeBinding,
MyMenuItem,
MyContextMenuService,
etc
)
Checklist
The folder(s) containing the DLL(s) is/are added to sys.path before loading. You may append, or sys.path.insert(0, dll_folder) to put it first on the list.
You call clr.AddReference('my_dll') without the dll extension (for my_dll.dll), after adding the folder to sys.path
The DLL Target Architecture is the same as the CPython version bitness. That is, if Architecture is x64, use 64-bit python, and if Architecture is x86, use 32-bit python. (instructions for this below)
How to check target Architecture for DLL?
I Used ILSpy (free and open source) -> Open DLL -> Check the output. Below example output.
What worked for me was to Unblock the dll file.
if u download the dll file or took it from different computer it might be blocked. So unblocked solved the issue for me.
To unblock right click on the properties if the dll file and check the Unblock box at the bottom

Categories