Я пишу диплом на тему оценки окружающей среды с использованием GIS. Для этого было написано пару скриптов на Python, которые последовательно подготавливали данные для получения необходимого результата. В первоначальном варианте я их просто последовательно запускал из панели ArcToolBox. Но со временем возникла необходимость создания единого пользовательского интерфейса. Для этих целей я его написал на PyGTK и уже от туда запускаю скрипты(теперь они в одном файле к часть одного класса).
Но возникла проблема, скрипт который работал раньше при запуске из панели ArcToolBox, теперь не хочет этого делать. Мне кажется, что это связано при запуске нового скрипта фокус передается на интерфейс написанный на PyGTK, а раньше был на ArcMap. Кто-нибудь сталкивался с такой проблемой раньше, или может быть объясните почему действительно это происходит? Если действительно из-за потерей связей, то как мне передавать фокус на мое приложение?
Здесь лежит мой скрипт.
Ссылка на скрипт, файл glade, и 2 картиночки
А это так строчка (187) которая не хочет запускаться
gp.Intersect_analysis("Air #;Finzal_Big_razrez", Air_sel, "ALL","#", "POINT")
gtk.main()
А вот полный текст скрипта:
#!/usr/bin/env python
# coding: utf-8
# Тут я импортирую все необходимые мне библиотеки
import sys
import threading
import os
try:
import pygtk
#tell pyGTK, if possible, that we want GTKv2
pygtk.require("2.0")
except:
#Some distributions come with GTK2, but not pyGTK
pass
try:
import gtk
import gtk.glade
except:
print "You need to install pyGTK or GTKv2 ",
print "or set your PYTHONPATH correctly."
print "try: export PYTHONPATH=",
print "/usr/local/lib/python2.2/site-packages/"
sys.exit(1)
# Импортирование нужных библиотек для ArcGIS
import string, arcgisscripting
gp = arcgisscripting.create()
# Необходимо для подключения к MS Access
import win32com.client
t = 0
s = os.path.abspath(os.curdir)
# Это была попытки в управлении потоками, но я в ней так особо и не понял.
# Идея была заблочить поток для GUI, и передать на работу с ГИС
class T(threading.Thread):
def __init__(self, n):
threading.Thread.__init__(self, name="t" + n)
self.n = n
def run(self):
print "Процесс", self.n
# Создание интерфейса и необходимых действий
class App():
def __init__(self):
# Загружаем файл интерфейса
self.gladefile = "Compl_.glade"
# дерево элементов интерфейса
self.widgetsTree = gtk.glade.XML(self.gladefile)
# Соединяем событие закрытия окна с функцией завершения приложения
self.window = self.widgetsTree.get_widget("window1")
if (self.window):
self.window.connect("destroy", self.close_app)
# Словарик, задающий связи событий с функциями-обработчиками
dic = {
"button2_clicked_cb": self.close_app,
"button1_clicked_cb": self.run,
"button3_clicked_cb": self.run_dir,
}
# Магическая команда, соединяющая сигналы с обработчиками
self.widgetsTree.signal_autoconnect(dic)
self.dir = self.widgetsTree.get_widget("window2")
self.dir.connect("delete-event", self.on_delete_event)
# Закрытие всего, не смог здесь понять как сработать с потоками
def close_app(self, widget):
#global p1
gtk.main_quit()
#p1.setDaemon(daemonic)
#quit
# Здесь происходит выбор и запуск соответсвующих частей кода
def run(self, widget):
self.cb1 = self.widgetsTree.get_widget("checkbutton1")
self.cb2 = self.widgetsTree.get_widget("checkbutton2")
self.cb3 = self.widgetsTree.get_widget("checkbutton3")
ch = [0,0,0,0,0]
if self.cb1.get_active() == 1:
ch[0] = 1
print ch
if self.cb2.get_active() == 1:
ch[1] = 1
print ch
if self.cb3.get_active() == 1:
ch[2] = 1
print ch
if self.cb4.get_active() == 1:
ch[3] = 1
print ch
if self.cb5.get_active() == 1:
ch[4] = 1
print ch
if ch[0] == 1:
self.source()
#os.startfile("D:/Gis/Compl/Scripts/MakeSource.py")
if ch[1] == 1:
self.clear_layer()
#os.startfile("D:/Gis/Compl/Scripts/clear_layer.py")
if ch[2] == 1:
self.intersect()
#os.startfile("D:/Gis/Compl/Scripts/Intersect.py")
if ch[3] == 1:
self.run_sql()
#os.startfile("D:/Gis/Compl/Scripts/Intersect.py")
# gtk.main_quit()
if ch[4] == 1:
self.color()
# Не совсем знаю для чего это надо, но оно не убивает мое второе всплывающее окно а прячет!
def on_delete_event(self, widget, event):
return self.dir.hide()
# ввод в поле редактирования пути к базе данных
def source(self):
self.entry = self.widgetsTree.get_widget("entry1")
self.entry.set_text("D:\Gis")
self.dir.show()
# Я храню путь к геобазе данных в текстовом файле, и здесь я его записываю в первый раз
# Дальше только считываю
def run_dir(self, widget):
s1 = self.entry.get_text()
print s1
# Заносим путь в Source.txt находящийся в тойже папке где и исполняемый скрипт
#raw_input()
f = file(s1+"/Compl/Scripts/Source.txt","w")
f.write(str(s1))
f.close()
self.dir.hide()
# Здесь происходит очитска слоев от результатов работы, эта часть работает без проблем!!!
def clear_layer(self):
gp.overwriteoutput = 1
# Считывание пути к базе данных из файла Source.txt
# s - путь к исполняемуму скрипту
print s
# Для запуска скрипта не из ArcGIS /Scripts/ необходимо убрать
f = file(s+"\\Source.txt","r")
#gp.addmessage(s)
a = f.read()
print a
#gp.addmessage(a)
# Указание рабочей области
gp.Workspace = a+"/WaterAirGB/WAGB.mdb/"
# Путь к таблице с которой будем работать
link_wst = a + "/WaterAirGB/WAGB.mdb/Finzal_Big_razrez"
# Работа на изменение таблицы
rows1 = gp.updatecursor(link_wst)
# Сбрасываем расположение курсора
rows1.reset()
# Первая строчка таблицы (следующая)
this_rows1 = rows1.next()
# Обнуление столбца grad в таблице
while this_rows1:
this_rows1.grad = 0
# gp.AddMessage(f(0))
rows1.UpdateRow(this_rows1)
this_rows1 = rows1.next()
gp.ResetEnvironments()
"""Эта та самая часть которая у меня перестала работать. Эта же часть работает отлично, вне интерфейса. Суть
ее заключается в том, что находит пересечение слоя полигонов Finzal_Big_razrez со слоем точеченых объектов Air. И та часть которая попадает в выделенную область
заносится в новый выходной слой Air_sel. Инструмент Intersect_analysis находил в работающей среде ArcMap
выбранный полигон и находил его пересечение с точенчным слоем. Результат - новый слой.
"""
def intersect(self):
gp.AddToolbox("C:/Program Files/ArcGIS/ArcToolbox/Toolboxes/Analysis Tools.tbx")
gp.ResetEnvironments()
gp.overwriteoutput = 1
# Считываем путь к базе геоданных
print s+" - intersect"
# Для запуска скрипта не из ArcGIS /Scripts/ необходимо убрать
f = file(s+"\\Source.txt","r")
gp.addmessage(s+" - absolute dir")
a = f.read()
print a+" - intersect"
gp.addmessage(a+" - to folder GIS")
gp.Workspace = a+"\\WaterAirGB\\WAGB.mdb\\"
self.GP.Workspace = a+"\\WaterAirGB\\WAGB.mdb\\"
# Устанавливаем пути к рабочим слоям
Air_sel = a+"\\WaterAirGB\\WAGB.mdb\\Air_sel"
#Air_sel = "D:\\Gis\\WaterAirGB\\WAGB.mdb\\Air_sel"
Finzal_Big_razrez = "Finzal_Big_razrez"
Air = "Air"
#gp.addmessage(Air_sel)
Pustoi = "Razb_finzal"
Water_sel = a+"\\WaterAirGB\\WAGB.mdb\\Water_sel"
Water = "Water"
#gp.addmessage(Water_sel)
Pustoi__2_ = "Razb_finzal"
Dno_sel = a+"\\WaterAirGB\\WAGB.mdb\\Dno_sel"
Dno = "Dno"
Pustoi__3_ = "Finzal_Big_razrez"
#gp.addmessage(Dno_sel)
try:
# Пересечение со слоев Air
#gp.Intersect_analysis("Air #;Finzal_Big_razrez #", "D:\Gis\WaterAirGB\WAGB.mdb\Air_sel", "ALL", "#", "POINT")
# та самая строчка что не работает
gp.Intersect_analysis("Air #;Finzal_Big_razrez", Air_sel, "ALL","#", "POINT")
# Пересечение со слоев Water
#gp.Intersect_analysis("Water #;Finzal_Big_razrez #", Water_sel, "ALL", "", "POINT")
# Пересечение со слоев Dno
#gp.Intersect_analysis("Dno #;Finzal_Big_razrez #", Dno_sel, "ALL", "", "POINT")
gp.addmessage("Well Done")
print "Well Done"
#raw_input()
except:
gp.addmessage("Ohh, no - it's not work")
print "Ohh, no - it's not work"
#raw_input()
# Эта часть выполняет подключение к MS Access и работаетр хорошо.
def run_sql(self):
# Подключенние через ADODB к Access
conn = win32com.client.Dispatch(r'ADODB.Connection')
f = file(s+"\\Source.txt","r")
a = f.read()
# Создаем подключение к базе WAGB.mdb
DSN = 'PROVIDER=Microsoft.Jet.OLEDB.4.0;DATA SOURCE='+a+'/WaterAirGB/WAGB.mdb;'
conn.Open(DSN)
# Создаем запросы SQL
clear_air = "DELETE FROM Airconc_sel"
clear_dno = "DELETE FROM Dnoconc_sel"
clear_water = "DELETE FROM Waterconc_sel"
sql_statement_air = "INSERT INTO Airconc_sel SELECT Airconc.* FROM Air_sel LEFT JOIN Airconc ON Air_sel.NUMBER_ = Airconc.NUMBER_;"
sql_statement_dno = "INSERT INTO Dnoconc_sel SELECT Dnoconc.* FROM Dno_sel LEFT JOIN Dnoconc ON Dno_sel.NUMBER_ = Dnoconc.NUMBER_;"
sql_statement_water = "INSERT INTO Waterconc_sel SELECT Waterconc.* FROM Water_sel LEFT JOIN Waterconc ON Water_sel.NUMBER_ = Waterconc.NUMBER_;"
# Выполнение запрсов
conn.Execute(clear_air)
conn.Execute(clear_dno)
conn.Execute(clear_water)
conn.Execute(sql_statement_air)
conn.Execute(sql_statement_dno)
conn.Execute(sql_statement_water)
conn.Close()
# Запуск программы Комплексной оценки
try:
os.startfile("C:/Program Files/Complex/Oleg_ivo.Complex.exe")
except:
print "Не запускается программа Complex"
raw_input()
# Эта часть раскрашивает полученный полигон соответсвующим цветом. Работоспособность еще не проверил.
def color(self):
f = file(s+"/Source.txt","r")
a = f.read()
print a
gp.overwriteoutput = 1
# Считываем данные из таблицы Compl
gp.Workspace = a+"/WaterAirGB/WAGB.mdb"
link_ws = a+"/WaterAirGB/WAGB.mdb/"
link_wst = a+"/WaterAirGB/WAGB.mdb/Compl"
rows = gp.searchcursor(link_wst)
rows.reset()
this_rows = rows.next()
s = []
while this_rows:
s.append(this_rows.getvalue("LLN"))
s.append(this_rows.getvalue("LN"))
s.append(this_rows.getvalue("N"))
s.append(this_rows.getvalue("HN"))
s.append(this_rows.getvalue("HHN"))
this_rows = rows.next()
print s
# Находим максимум и сохраняем в f
RANG = [1,2,3,4,5]
f = [1,s[0]]
for i in range(0,5):
if (s[i] >= f[1]):
f[1] = s[i]
f[0] = RANG[i]
print f
# Находим выбранные объекты через пересчение слоев
gp.Workspace = a+"/WaterAirGB/"
gp.AddToolbox("C:/Program Files/ArcGIS/ArcToolbox/Toolboxes/Analysis Tools.tbx")
Pustoi_Select = a+"/WaterAirGB/WAGB.mdb/Finzal_Big_razrez_s"
Pustoi = "Finzal_Big_razrez"
try:
gp.Select_analysis(Pustoi, Pustoi_Select, "")
except:
gp.Addmessage("Выборка не работает, перезапустите проект Compl.mxd")
# Наход ID выбранных объектов
link_wst = a+"/WaterAirGB/WAGB.mdb/Finzal_Big_razrez"
rows = gp.searchcursor(link_wst)
rows.reset()
this_rows = rows.next()
s = []
while this_rows:
s.append(this_rows.getvalue("ID"))
this_rows = rows.next()
print s
# Раскрашиваем согласно данным в f
link_wst = a+"/WaterAirGB/WAGB.mdb/Finzal_Big_razrez"
rows1 = gp.updatecursor(link_wst)
rows1.reset()
this_rows1 = rows1.next()
rows2 = gp.searchcursor(link_wst)
rows2.reset()
this_rows2 = rows2.next()
while this_rows1:
if (this_rows2.getvalue("ID") in s):
this_rows1.grad = f[0]
rows1.UpdateRow(this_rows1)
this_rows2 = rows2.next()
this_rows1 = rows1.next()
gp.resetenvironments()
if __name__ == "__main__":
#p1 = T(gtk.main())
app = App()
#p1.start()
gtk.main()# Мне кажется из-за этой команды не хочет выполнятся intersect_analysis
P.S. Я не силен в написании скриптов на Python и в програмировании, а привиденный скрипт я хоть и сделал сам, но по образу и подобию чужих наработок. Например, с понятием class я не особо знаком, но понял как работает, и потому стал его использовать! Может это было и излишне!