2017-06-07 2 views
1

私は、OracleからArcMapにデータを抽出するために使用する2つのpythonクラスオブジェクトを持っています。このプロセスのさまざまなアクティビティによって、私は「列」オブジェクトのリストから始まり、pyTableオブジェクトを構築します。 pyTableオブジェクトには名前でフィールドを挿入するリストがあります。 __init__の間に私はgetSelect()関数を使用して、挿入フィールドのリストを設定します。クラスは入力オブジェクトを複製します

pyTableを呼び出すたびに新しく作成されたオブジェクトが取得されることを確認するために一連の文を追加しましたが、私はまだ奇妙な結果が見られます。私がクラスを初めて使うときは、すべて大丈夫です。同じ文を2回発行すると、colListは新しいですが、フィールドリストは重複しています。無関係なコードセクションを掃除しないという私の謝罪。

ここで、私はオブジェクト参照を乱していますか?

ここに実行結果があります。 myListには8つの列オブジェクトがあります。ここで

>>> arcTable = pyTable(myList) 
>>> len(arcTable.getTuple()) 
8 
>>> arcTable = pyTable(myList) 
>>> len(arcTable.getTuple()) 
16 
>>> arcTable = pyTable(myList) 
>>> len(arcTable.getTuple()) 
8 
>>> arcTable = pyTable(myList) 
>>> len(arcTable.getTuple()) 
8 
>>> newTable = pyTable(myList) 
>>> len(newTable.getTuple()) 
8 
>>> thirdTable = pyTable(myList) 
>>> len(thirdTable.getTuple()) 
16 
>>> thirdTable = pyTable(myList) 
>>> len(thirdTable.getTuple()) 
24 
>>> thirdTable = pyTable(myList) 
>>> len(thirdTable.getTuple()) 
8 
>>> 

2クラスです:

import arcpy, cx_Oracle 

class column: 
    # Add to the arcType and cxType functions to support more Oracle data types. 
    # BLOB and CLOB fields will need additional support in Read and Write fx's. 
     name = '' 
     dataType = '' 
     dataLen = 1 
     dataPrecision = 0 
     dataScale = 0 
     query = '' 
     isShape = False 
     isLOB = False 

     def __init__(self, Name, DataType, DataLen, DataPrecision, DataScale): 
      self.name = Name 
      self.dataType = DataType 
      self.dataLen = DataLen 
      self.dataPrecision = DataPrecision 
      self.dataScale = DataScale 
      if DataType == 'WKT': 
       self.query = 'sdo_util.to_wktgeometry(t.' + Name + ') wkb, ' 
      else: 
       self.query = 't.' + Name 
      if DataType == 'SDO_GEOMETRY': 
       self.isShape = True 
      if DataType == 'BLOB' or DataType == 'CLOB' or DataType == 'WKT': 
       self.isLOB = True 

     def getArcType(self, *args):  # Data type translation 'Oracle_type':'ESRI_type' 
      return { 
#    'BINARY_DOUBLE':'DOUBLE', 
#    'BINARY_FLOAT':'FLOAT', 
#    'BLOB':'BLOB', 
       'CHAR':'STRING', 
       'CLOB':'CLOB', 
       'DATE':'DATE', 
#    'FLOAT':'FLOAT', 
#    'LONG':'LONG', 
#    'LONG RAW':'BLOB', 
       'NUMBER':'DOUBLE', 
#    'RAW':'BLOB', 
#    'ROWID':'SHORT', 
       'SDO_GEOMETRY':'GEOMETRY', 
       'VARCHAR2':'STRING', 
       'WKT':'WKT', 
      }.get(self.dataType,"undefined") 

     def getCxType(self, *args):  # Data type translation 'Oracle_type':'cx_Oracle.type' 
      return { 
       'BLOB':cx_Oracle.BLOB, 
       'CHAR':cx_Oracle.STRING, 
       'CLOB':cx_Oracle.CLOB, 
       'DATE':cx_Oracle.DATETIME, 
       'NUMBER':cx_Oracle.NUMBER, 
       'SDO_GEOMETRY':cx_Oracle.CLOB, 
       'VARCHAR2':cx_Oracle.STRING, 
      }.get(self.dataType,"undefined") 

class pyTable: 
    # Create an object to track columns for read and write operations. 
    # BLOB, CLOB and SDO_GEOMETRY types will need additional support in Read and Write fx's. 
    length = 0 
    # colList = []  # The original list of columns is coming from an Oracle query. 
    # These two lists are different because of the way I treat shape. 
    # I create a FC and then add attribute columns. This puts the Shape column first in the list. 
    __insCols = []  # I use insCols as a list of column type objects to write to ArcMap. 
    __insertFields = [] 
    __colTuple = None 
    __myData = [] 
    __pKey = 'P_KEY'  # The name of the primary key field should be <table>_CN 
    __insBlobCols = [] # A list of column positions that contain BLOB data types. 
    __insKeyCol = -1  # The position of the primary key column. 

    def __init__(self, ColList): 
     self.colList = ColList[:] 
     self.length = len(ColList) 
     self.isFC = self.__getShape() 
     self.__select = self.getSelect() 
     arcpy.AddMessage('New table class created with ' + str(self.length) + ' columns.') 

    def __del__(self): 
     self.colList = [] 
     del self.__insCols [:] 
     del self.__insertFields [:] 
     del self.__myData [:] 
     del self.__insBlobCols [:] 

    def addDataRow(self, inDataRow): 
     self.__myData.append(inDataRow) 

    def getInsCols(self): 
     return self.__insCols 

    def getTuple(self): 
     return self.__colTuple 

    def getPK(self): 
     return self.__pKey 

    def getInsBlobCols(self): 
     return self.__insBlobCols 

    def clearData(self): 
     self.__myData = [] 

    def getData(self): 
     return self.__myData 

    def getKeyCol(self): 
     return self.__insKeyCol 

    def __getShape(self): 
     isFeature = False 
     featureName = '' 
     for col in self.colList: 
      if col.isShape: 
       isFeature = True 
       featureName = col.name 
     if isFeature: 
      wktShape = column(featureName, 'WKT', 0, 0, 0) 
      self.__insCols.append(wktShape) 
     for col in self.colList: 
      if not col.isShape: 
       self.__insCols.append(col) 
     return isFeature 

    def getSelect(self): 
     # Build the select statement 
     # Build the list of insert Field names 
     # Build the Tuple of insert Field names 
     # Identify the LOB columns by index number 
     statement = 'select ' 
     del self.__insertFields[:] 
     indx = 0 
#  print ('Table has ', len(self.__insCols), ' insert columns.') 
     for col in self.__insCols: 
      if col.dataType == 'WKT': 
       statement += 'sdo_util.to_wktgeometry(t.shape) wkb, ' 
       self.__insertFields.append('[email protected]') 
      else: 
       statement += 't.' + col.name + ', ' 
       self.__insertFields.append(col.name) 
       if col.dataType == 'BLOB': 
        self.__insBlobCols.append(indx) 
      # 
      # ToDo: The key column should be <table>_CN 
      # But, the logic needs to work for views with different names. 
      # 
      if col.name == self.__pKey: 
       self.__insKeyCol = indx 
      indx += 1 
     statement = statement[:statement.rfind(',')] # Trim off the trailing comma 
#  print ('Insert is composed of ', len(self.__insertFields), ' fields.') 
     self.__colTuple = tuple(self.__insertFields) 
     return statement 

    def createTemp(self, WorkSpace, tempFC): 
     success = False 
     insertCols = self.__insCols 
     arcpy.AddMessage('Adding ' + tempFC + ' with ' + str(len(insertCols)) + ' columns.') 
     try: 
      if self.isFC: 
       arcpy.CreateFeatureclass_management(WorkSpace, tempFC, 'POINT') 
       arcpy.AddMessage(tempFC + ' feature class was successfully created.') 
      else: 
       arcpy.CreateTable_management(WorkSpace, tempFC) 
       arcpy.AddMessage(tempFC + ' table was successfully created.') 
      for col in insertCols: 
       esriType = col.getArcType() 
       if esriType == "undefined": 
        arcpy.AddError('Data type not currently supported, ' + col.dataType) 
        return success 
       if col.dataType <> 'WKT': 
        arcpy.AddField_management(tempFC, col.name, esriType, col.dataPrecision, col.dataScale, col.dataLen) 
        arcpy.AddMessage('Created column: ' + col.name) 
      success = True 
     except: 
      e = sys.exc_info()[1] 
      arcpy.AddError('Create of ' + tempFC + ' failed with ' + str(e.args[0]))    
     return success 

答えて

1

あなたは、init関数であなたのクラスに渡されたリストのシャローコピーを作っています。

いくつかの基本情報については、PythonのマニュアルのShallow and deep copy operationsを参照してください。

self.colList = ColList[:]は新しいリストを作成しますが、その新しいリストの中には元のリスト(浅いコピー)にあったものと同じオブジェクトへの参照です。

あなたは深いコピーが必要になります。

import copy 
... 
self.colList = copy.deepcopy(ColList) 

ディープコピーが新しいリストだけでなく、元のリスト内のオブジェクトに一致するように初期化された新しいオブジェクトを持っています。したがって、あるクラスのリストのオブジェクトが変更された場合、それらはすべてのクラスで変更されません。

+0

ありがとうございました。私はPython 2.7環境でコピーライブラリをインポートしなければなりませんでした。あなたの提案が鍵でした。 – user2948567

関連する問題