Расширение Inkscape: python не вызывает.exe
Я разрабатываю плагин для Inkscape. Некоторые версии:
- Inkscape v0.92.3
- Windows 10, версия 1803 (сборка 17134.165)
- Python 3.7 явно установлен
- MonoDevelop Version 7.7 Preview (7.7) Дополнительные версии ниже
Места установки:
- Inkscape: C: \ Program Files \ Inkscape
- Расширение: C:\Program Files\Inkscape\share\extensions
- Содержит:
myplugin.inx
,myplugin.py
,MyPlugin.exe
- Содержит:
Я сделал плагин, который по причинам разработки работает так, как задумано в настоящее время.
Наиболее важно то, что он запускается, когда я запускаю его либо из MonoDevelop, либо из самого встроенного exe-файла (как с сгенерированными DLL-файлами и т. Д. В одном месте, так и только с файлом, скопированным в другое место).
Я использую (слегка отредактированную версию) скрипт Python SugarPillStudio для запуска файла.exe. Однако когда я запускаю этот скрипт на Python, вызывая расширение,.exe не запускается. Inkscape мигает сообщением "MyPlugin запускается..." и закрывает его так же быстро, как и открывается.
Я знаю, что скрипт python работает, потому что он выводит строки отладки в файл.log на моем рабочем столе. Я знаю, что.exe не запускается, потому что он также записывает строки в тот же файл.log, во-первых, когда вызывается main(). Когда я (успешно) запускаю.exe, он печатает в файл, а когда я запускаю расширение - нет.
Это наводит меня на мысль, что есть проблема со скриптом python при вызове.exe. Любая помощь?
Python Script:
#!/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]
Plugin.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>
Варианты Extra 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
2 ответа
Исходя из файла pathops.py, на который Moini в своем ответе, я Moini следующий файл.
Около
Он использует библиотеку inkex.py ( источник на GitLab) для объявления Inkscape Effect
, Effect
класс использует OptionParser
библиотека для анализа заданных по умолчанию параметров (например, --id=$$
для выбранных узлов, где $$
является значением тега 'id' узла XML). Добавив кастом executable
вариант, мы также можем разобрать это.
Разбор аргументов
После OptionParser
выполняется разбор, значения будут видны в self.options
наш исполняемый файл теперь находится в self.options.executable
(из-за action="store"
а также dest="executable"
параметры).
Кроме того, временный SVG-файл, созданный Inkscape, можно найти в self.svg_file
,
Сохранение правок
Как было сказано ранее, Inkscape создает временный файл с содержимым SVG в его текущем состоянии. Любые изменения, которые вы (r плагин) делаете (и) не должны быть сохранены обратно в этот файл, но должны быть возвращены в сам Inkscape - это предпосылка Effect
класс: он редактирует SVG и возвращает редактирование в Inkscape. Дальнейшее чтение здесь.
Вместо этого в вашем плагине вы должны (только для чтения) открыть файл, прочитать его содержимое, а затем отредактировать его. Когда вы закончите редактирование, напишите весь SVG в вашу командную строку.
Затем линия out, err = process.communicate(None)
захватит вывод вашего плагина и вывод ошибок. Они используются для возврата информации в Inkscape.
Заметки
Структура cmd
Массив не имеет значения, за исключением того факта, что исполняемый файл должен быть первым элементом. Все остальные элементы массива могут быть в любом порядке, я просто добавил '--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()
Inkscape использует Python 2.7, который поставляется вместе с ним, если только вы не установите это в файле настроек (отредактируйте вручную).
Если вы хотите написать расширение Inkscape, вы можете узнать, как это сделать:
- чтение https://inkscape.org/develop/extensions/
- следуя примерам в других расширениях, которые работают (например, для запуска дополнительных экземпляров Inkscape, вы можете следовать этому: https://gitlab.com/su-v/inx-pathops/blob/master/src/pathops.py)