【问题标题】:Inkscape extension: python doesn't invoke .exeInkscape 扩展:python 不调用 .exe
【发布时间】:2018-08-02 09:52:24
【问题描述】:

我正在为 Inkscape 开发一个插件。一些版本:

  • Inkscape v0.92.3
  • Windows 10 版本 1803(内部版本 17134.165)
  • 显式安装 Python 3.7
  • MonoDevelop 版本 7.7 预览版 (7.7) 以下额外版本

安装地点:

  • Inkscape:C:\Program Files\Inkscape
  • 扩展名:C:\Program Files\Inkscape\share\extensions
    • 包含:myplugin.inxmyplugin.pyMyPlugin.exe

出于开发原因,我制作了一个插件,该插件可以按当前预期工作。
最重要的是,当我从 MonoDevelop 或构建的 exe 本身运行它时,它会运行(无论是在同一位置生成的 .dll 等,还是仅将 exe 复制到不同的位置) )。

我使用SugarPillStudio's python script(稍加编辑的版本)来运行 .exe 文件。但是,当我通过调用扩展程序运行该 python 脚本时,不会启动 .exe。 Inkscape 闪烁显示“MyPlugin 正在启动...”的消息,并在打开时立即关闭。

我知道 python 脚本可以工作,因为我让它将调试行打印到我桌面上的 .log 文件中。我知道 .exe 不会启动,因为我还让它在同一个 .log 文件中写入行,这是调用 main() 时的第一件事。当我(成功)运行 .exe 时,它​​会打印到文件中,而当我运行扩展程序时,它不会。

这让我相信 python 脚本在调用 .exe 时存在问题。有什么帮助吗?

Python 脚本:

#!/usr/bin/env python
'''
sugarpillstudios.com/wp/?p=142
'''
import os, sys, subprocess, datetime

f=open("C:\Users\Diamundo\Documents\plugin.log", "a+")
f.write("[PYT] %s Python script called at: %s.\n" % (datetime.datetime.now().isoformat(), os.getcwd() ) )

argv = []  
for arg in sys.argv[:]:  
  if arg.startswith("--executable="):  
    executable = arg.split("=")[1]  
  else:  
    argv.append(arg)
argv[0] = executable  
f.write("[PYT] %s %s\n" % ( datetime.datetime.now().isoformat(), executable ) )
process = subprocess.Popen(argv,shell=False,stdout=subprocess.PIPE)
print process.communicate()[0]

插件.inx:

<inkscape-extension>
    <name>MyPlugin</name>
    <id>name.space.plugin.main</id>
    <param name="executable" type="string" gui-hidden="true">MyPlugin.exe</param>
    <effect>
        <object-type>all</object-type>
        <effects-menu>
            <submenu _name="MyPlugin"/>
        </effects-menu>
    </effect>
    <script>
        <command reldir="extensions" interpreter="python">myplugin.py</command>
    </script>
</inkscape-extension>

额外的 Monodevelop 版本:

Runtime:
    Microsoft .NET 4.0.30319.42000
    GTK+ 2.24.26 (Light theme)
    GTK# 2.12.45

NuGet 
Version: 4.3.1.4445

.NET Core
Runtime: C:\Program Files\dotnet\dotnet.exe
Runtime Versions:
    2.0.9
    2.0.5
SDK: C:\Program Files\dotnet\sdk\2.1.202\Sdks
SDK Versions:
    2.1.202
    2.1.4
MSBuild SDKs: Not installed

【问题讨论】:

    标签: python subprocess inkscape


    【解决方案1】:

    Inkscape 使用它自带的 Python 2.7,除非您在设置文件中进行不同的设置(手动编辑)。

    如果你想编写一个 Inkscape 扩展,你可以通过以下方式学习如何做到这一点:

    【讨论】:

    • 我知道 Inkscape 附带的 Python,但是我另外安装了 3.7 以查看是否可以解决问题 - 显然不是。
    • 关于您的链接页面的更多信息,我已经很熟悉它们了,我只是在使用 C#/Mono 时受到限制,所以不幸的是,仅使用 Python 是不可能的......跨度>
    • 如果您需要使用不同的 python 可执行文件,您需要在您的设置文件中手动设置它,即使用文本编辑器打开。更多信息在这里:wiki.inkscape.org/wiki/index.php/Extension_Interpreters
    • 另外,我不明白 sys.argv[:] 应该来自哪里。如何使用参数调用 python 扩展?...
    • 在 Inkscape 之外运行其他程序应该像 pathops 扩展链接中给出的示例一样工作。
    【解决方案2】:

    基于pathops.py 文件,由Moiniher answer 链接,我想出了以下文件。

    关于

    它使用inkex.py (source on GitLab) 库来声明Inkscape EffectEffect 类使用 OptionParser 库来解析默认的给定参数(例如,--id=$$ 用于选定节点,其中 $$ 是 XML 节点的“id”标签的值)。通过添加自定义executable选项,我们也可以解析这个。

    解析参数

    OptionParser 解析完成后,值将在self.options 中可见,即我们的可执行文件现在位于self.options.executable 中(因为action="store"dest="executable" 参数)。
    此外,Inkscape 创建的临时 SVG 文件可以在 self.svg_file 中找到。

    保存编辑

    如前所述,Inkscape 制作了一个 临时 文件,其中包含 SVG 的当前状态。您(r 插件)所做的任何编辑都应该保存回这个文件,而是返回到 Inkscape 本身 - 这是 Effect 类的前提:它编辑 SVG 并返回对 Inkscape 的编辑。 Further reading here.

    相反,您应该在您的插件中(只读)打开文件,读取其内容,然后对其进行编辑。完成编辑后,将整个 SVG 写入命令行。
    然后,out, err = process.communicate(None) 行将获取插件的输出和错误输出。 这些用于将信息返回给 Inkscape。

    注意事项

    cmd 数组的结构并不重要,除了可执行文件应该作为第一个元素出现。所有其他数组元素可以是任何顺序的任何东西,我只是在每个 ID 中添加了'--id=$$',因为这是 Inkscape 使用的方式,这样看起来就好像没有 Python 中间件存在一样。我最后放置的 self.svg_file 也是如此,Inkscape 在其参数中也是如此 - 为了清楚起见,您也可以从中创建 '--file='+self.svg_file

    来源

    #!/usr/bin/env python
    
    import os
    from subprocess import Popen, PIPE
    import time
    
    try:
        import inkex_local as inkex
    except ImportError:
        import inkex
    #import simplestyle
    
    class MyPlugin(inkex.Effect):
        def __init__(self):
            inkex.Effect.__init__(self)
            self.OptionParser.add_option("--executable", action="store", type="string", dest="executable", default="MyPlugin.exe")
    
        def effect(self):
            out = err = None
    
            cmd = []
            cmd.append(self.options.executable)
            for id in self.options.ids:
                cmd.append("--id=" + id)
            cmd.append(self.svg_file)
            #inkex.debug(cmd);
    
            process = Popen(cmd, shell=False, stdin=PIPE, stdout=PIPE, stderr=PIPE)
            out, err = process.communicate(None)
    
            if process.returncode == 0:
                print out
            elif err is not None:
                inkex.errormsg(err)
    
    if __name__ == '__main__':
        myplugin = MyPlugin()
        myplugin.affect()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-24
      • 2021-12-02
      • 1970-01-01
      相关资源
      最近更新 更多