Я написал кучу Python кода для пометки файлов наших поставщиков в Solidworks PDM, и я пытаюсь использовать API Solidworks PDM для фактического применения этой информации. Официально API поддерживает только C# и VB, но я бы хотел сохранить все в Python, если это возможно, потому что все остальное уже в Python (и этот язык мне наиболее удобен для программирования). Вот высокоуровневый список того, что я пытаюсь выполнить sh:
- Проверьте несколько файлов
- Обновите переменную карты данных
- Проверьте эти файлы обратно в
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' )),
Есть идеи?