Python win32com和二维数组
当使用python和win32com自动化软件表单Adobe时,会遇到传递二维坐标数组的问题。如果你看一看Adobe为visual basic(VB)提供的代码,就会发现它很简单。在Illustrator中绘制线条的简化示例如下所示:Python win32com和二维数组,python,multidimensional-array,coordinates,win32com,Python,Multidimensional Array,Coordinates,Win32com,当使用python和win32com自动化软件表单Adobe时,会遇到传递二维坐标数组的问题。如果你看一看Adobe为visual basic(VB)提供的代码,就会发现它很简单。在Illustrator中绘制线条的简化示例如下所示: Set appObj = CreateObject("Illustrator.Application") Set docObj = appObj.Documents.Add Set pathItem = docObj.PathItems.Add path
Set appObj = CreateObject("Illustrator.Application")
Set docObj = appObj.Documents.Add
Set pathItem = docObj.PathItems.Add
pathItem.SetEntirePath Array(Array(0.0, 0.0), Array(20.0, 20.0))
from win32com.client import Dispatch
appObj = Dispatch("Illustrator.Application")
docObj = appObj.Documents.Add()
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( [ [0.0,0.0], [20.0,20.0] ] )
from win32com.client import Dispatch, VARIANT
from pythoncom import VT_VARIANT
import collections
appObj = Dispatch("Illustrator.Application")
docObj = appObj.Documents.Add()
def variant(data):
return VARIANT(VT_VARIANT, data)
def vararr(*data):
if ( len(data) == 1 and
isinstance(data, collections.Iterable) ):
data = data[0]
return map(variant, data)
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [0.0,0.0], [20.0,20.0] ) )
#or you can have a iterable of iterables
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [[30.0,10.0], [60.0,60.0]] ) )
现在,天真的假设是,VB代码可以通过如下方式转换为python:
Set appObj = CreateObject("Illustrator.Application")
Set docObj = appObj.Documents.Add
Set pathItem = docObj.PathItems.Add
pathItem.SetEntirePath Array(Array(0.0, 0.0), Array(20.0, 20.0))
from win32com.client import Dispatch
appObj = Dispatch("Illustrator.Application")
docObj = appObj.Documents.Add()
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( [ [0.0,0.0], [20.0,20.0] ] )
from win32com.client import Dispatch, VARIANT
from pythoncom import VT_VARIANT
import collections
appObj = Dispatch("Illustrator.Application")
docObj = appObj.Documents.Add()
def variant(data):
return VARIANT(VT_VARIANT, data)
def vararr(*data):
if ( len(data) == 1 and
isinstance(data, collections.Iterable) ):
data = data[0]
return map(variant, data)
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [0.0,0.0], [20.0,20.0] ) )
#or you can have a iterable of iterables
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [[30.0,10.0], [60.0,60.0]] ) )
显然,这并不是那么容易,python发出了一个错误,说“只支持维度为1的数组”。现在我知道数组的数组和二维数组之间有区别。所以问题是如何强制python生成正确类型的数组
我试着制作自己的变体,但惨败了。为此,我还查看了ctypes。有没有人有过同样的问题,并能提供一些线索
附言:
我知道这个问题可以通过以下方法解决:
pathItem = docObj.PathItems.Add()
for point in ( [0.0,0.0], [20.0,20.0] ):
pp = pathItem.PathPoints.Add()
pp.Anchor = point
但也有类似的情况,这实际上不起作用。无论如何,重点是编写关于向学生移植的指导原则,以便尽可能接近原始意图。我在尝试使用win32com确定选择区域时遇到了同样的问题。我发现使用comtypes而不是win32com访问photoshop彻底解决了多维数组问题 我相信一维数组问题是win32com的一个局限,但我可能错了 您可以在此处获取comtypes: 有一篇关于这个问题的帖子值得一看 下面是一个使用上面链接的技术艺术家论坛帖子中的comtypes通过数组的示例。路径点的实现应该类似
import comtypes.client
ps_app = comtypes.client.CreateObject('Photoshop.Application')
# makes a new 128x128 image
ps_app.Documents.Add(128, 128, 72)
# select 10x10 pixels in the upper left corner
sel_area = ((0, 0), (10, 0), (10, 10), (0, 10), (0, 0))
ps_app.ActiveDocument.Selection.Select(sel_area)
下面是一个实际使用Win32 COM模块的替代解决方案。碰巧,Illustrator和Photoshop的数组类型是一个变体类型的单一数组。其中,变量类型也是一个数组。还有其他应用程序,如solidworks,也使用相同的策略。您可以使用以下代码强制win32com生成变量类型:
from win32com.client import VARIANT
from pythoncom import VT_VARIANT
def variant(data):
return VARIANT(VT_VARIANT, data)
方便的做法是,您不必总是在任何地方键入variant,因此您只需使用python数组,并使用以下内容使每个子元素都变为variant:
import collections
def vararr(*data):
if ( len(data) == 1 and
isinstance(data, collections.Iterable) ):
data = data[0]
return map(variant, data)
最后,我的完整代码如下所示:
Set appObj = CreateObject("Illustrator.Application")
Set docObj = appObj.Documents.Add
Set pathItem = docObj.PathItems.Add
pathItem.SetEntirePath Array(Array(0.0, 0.0), Array(20.0, 20.0))
from win32com.client import Dispatch
appObj = Dispatch("Illustrator.Application")
docObj = appObj.Documents.Add()
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( [ [0.0,0.0], [20.0,20.0] ] )
from win32com.client import Dispatch, VARIANT
from pythoncom import VT_VARIANT
import collections
appObj = Dispatch("Illustrator.Application")
docObj = appObj.Documents.Add()
def variant(data):
return VARIANT(VT_VARIANT, data)
def vararr(*data):
if ( len(data) == 1 and
isinstance(data, collections.Iterable) ):
data = data[0]
return map(variant, data)
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [0.0,0.0], [20.0,20.0] ) )
#or you can have a iterable of iterables
pathItem = docObj.PathItems.Add()
pathItem.SetEntirePath( vararr( [[30.0,10.0], [60.0,60.0]] ) )
是的,这可以通过comtypes实现,但这回答了我的问题,即如何在Win32 COM中实现这一点。此外,使用win32com还有一些原因,例如能够生成常量。因此,经过很长一段时间,我终于找到了一个真正困扰我的问题的答案。希望这对某人有所帮助。是的,这是可行的,只是我更愿意在win32com中这样做,因为默认情况下这些计算机上都会提供这种功能。哦,我想再和IT部门协商一个月吧。