Solidworks PDM API в Python - получение объекта AttributeError не имеет атрибута QueryInterface - PullRequest
0 голосов
/ 08 марта 2020

Я написал кучу Python кода для пометки файлов наших поставщиков в Solidworks PDM, и я пытаюсь использовать API Solidworks PDM для фактического применения этой информации. Официально API поддерживает только C# и VB, но я бы хотел сохранить все в Python, если это возможно, потому что все остальное уже в Python (и этот язык мне наиболее удобен для программирования). Вот высокоуровневый список того, что я пытаюсь выполнить sh:

  1. Проверьте несколько файлов
  2. Обновите переменную карты данных
  3. Проверьте эти файлы обратно в

API определяет два способа основных способов регистрации / извлечения / обновления переменных в отдельных файлах - один для отдельных файлов и один для групп файлов. Вы можете использовать методы, доступные через интерфейс IEdmVault5, чтобы выполнить все 3 операции над отдельными файлами, а для выполнения этих операций над группами файлов необходимо использовать 3 отдельных интерфейса - IEdmBatchGet (checkout), IEdmBatchUpdate2 (обновить переменные) и IEdmBatchUnlock ( регистрироваться).

Я смог написать функциональный код, который выполняет все 3 действия для каждого отдельного файла, но он работал медленно при работе со многими файлами - моя цель - обновить пару тысяч файлов одновременно. Заставить работать пакетные интерфейсы оказалось гораздо сложнее, но я смог в конечном итоге получить пакетную проверку и регистрацию работ (и это определенно стоило того - каждая операция была примерно в 10 раз быстрее с использованием интерфейса хранилища). Тем не менее, я застрял, пытаясь заставить работать переменное обновление. Вот мой код для обновления переменных:

import win32com.client
import os

import comtypes.client as cc
cc.GetModule('C:\Program Files (x86)\SOLIDWORKS PDM\EdmInterface.dll')
import comtypes.gen._5FA2C692_8393_4F31_9BDB_05E6F807D0D3_0_5_22 as pdm_lib2

vault_name = 'vault_name'
folder_path = 'some_folder_path'

def connect_to_vault(vault_name, lib = 'comtypes'):
    if lib == 'comtypes':
        vault = cc.CreateObject('ConisioLib.EdmVault.1')
        vault.LoginAuto(vault_name, 0)

    else: 
        vault = win32com.client.dynamic.Dispatch('ConisioLib.EdmVault.1')
        vault.LoginAuto(vault_name, 0)

    return vault

def getrefs(vault, filenames, folder_path):
    DocIDs = []
    ProjIDs = []

    for filename in filenames:
        temp_ProjID = vault.GetFolderFromPath(folder_path)
        temp_DocID = vault.GetFileFromPath(filename, temp_ProjID)[0] #this fails when I use a comtypes generated vault

        DocIDs.append(temp_DocID.ID)
        ProjIDs.append(temp_ProjID.ID)

    print('Document and Project IDs pulled')

    return DocIDs, ProjIDs

vault = connect_to_vault(vault_name)
ref_vault =connect_to_vault(vault_name, lib = 'win32com') 

filenames = [folder_path + s for s in os.listdir(folder_path)]
DocIDs, ProjIDs = getrefs(ref_vault, filenames, folder_path)

#Using Comtypes to update files
VarIDs = [54] * len(DocIDs) #Updating description only
var_values = [['foo' + str(s)] for s in range(len(DocIDs))] #dummy values for now

update_vars = vault.CreateUtility(2) #create instance of BatchUpdate 

for i, file in enumerate(DocIDs): 
    update_vars.SetVar(file, VarIDs[i], var_values[i], '', 1)

pdm_error = [pdm_lib2.EdmBatchError2()] * len(DocIDs)
update_vars.CommitUpdate([pdm_error])

Когда я вызываю update_vars.CommitUpdate ([pdm_error]), я получаю следующую ошибку:

ArgumentError: argument 2: <class 'AttributeError'>: 'list' object has no attribute 'QueryInterface'

Я не уверен, почему это Метод ожидает объект с атрибутом QueryInterface - я передаю ему только список структур, а не полный COM-объект, такой как мое хранилище файлов. Я также попытался использовать win32com для выполнения метода:

update_vars = ref_vault.CreateUtility(2) #create instance of BatchUpdate, use win32com instead

for i, file in enumerate(DocIDs): 
    update_vars.SetVar(file, VarIDs[i], var_values[i], '', 1)

pdm_error = [pdm_lib2.EdmBatchError2()] * len(DocIDs)
update_vars.CommitUpdate([pdm_error])

И теперь я получаю эту ошибку:

Traceback (most recent call last):

  File "<ipython-input-222-0c49fb0861b9>", line 7, in <module>
    update_vars.CommitUpdate([pdm_error])

  File "D:\Users\apreacher\Documents\Shared Files\Python\Webscraping_projects\Helper Modules\pdm_lib.py", line 1500, in CommitUpdate
    , poCallback)

  File "C:\Users\apreacher\AppData\Local\Continuum\anaconda3\lib\site-packages\win32com\client\__init__.py", line 467, in _ApplyTypes_
    self._oleobj_.InvokeTypes(dispid, 0, wFlags, retType, argTypes, *args),

MemoryError: CreatingSafeArray

И вот где я застрял. Я не смог добиться успеха в том, чтобы заставить метод CommitUpdate работать должным образом. У меня также есть определения методов из файлов, созданных makepy.py и comtypes, но я не знаю, как их интерпретировать:

определение метода makepy.py:

def CommitUpdate(self, ppoRetErrors=pythoncom.Missing, poCallback=0):
    'method Commit'
    return self._ApplyTypes_(3, 1, (3, 0), ((24612, 2), (9, 49)), 'CommitUpdate', None,ppoRetErrors
        , poCallback)

сгенерированный файл:

COMMETHOD([dispid(3), helpstring('method Commit')], HRESULT, 'CommitUpdate',
          ( ['out'], POINTER(_midlSAFEARRAY(EdmBatchError2)), 'ppoRetErrors' ),
          ( ['in', 'optional'], POINTER(IEdmCallback), 'poCallback', 0 ),
          ( ['out', 'retval'], POINTER(c_int), 'plErrorCount' )),

Есть идеи?

...