Форум сайта python.su
Доброго времени суток!
Подскажите, как вызвать внешнюю программу с параметрами, и, если возможно, перенаправить ее лог в текстовое поле?
Вот, например, на autoit писал вызов так:
$Conv="D:\TC\WPI_VOG\Apps\MyHomeLib\converters\fb2converter\fb2c.exe"
$Conv_Ini="D:\TC\WPI_VOG\Apps\MyHomeLib\converters\fb2mobi\fb2mobi.toml"
$Fb2In ="J:\My_project_programming\Converter\test\FB2"
$MobiOut="J:\My_project_programming\Converter\test\Mobi"
RunWait($Conv & ' -c ' & $Conv_Ini & ' convert --to mobi ' & $Fb2In & ' ' & $MobiOut & ' --ow ', "", @SW_HIDE)
import subprocess Converter = "D:\\TC\\WPI_VOG\Apps\\MyHomeLib\\converters\\fb2converter\\fb2c.exe" ConverterIni = "D:\\TC\\WPI_VOG\\Apps\\MyHomeLib\\converters\\fb2mobi\\fb2mobi.toml" Fb2In = "J:\\My_project_programming\\Converter\\test\\FB2" MobiOut= "J:\\My_project_programming\\Converter\\test\\Mobi" def main(): subprocess.Popen([Converter, ' -c ', ConverterIni, ' convert --to mobi ', Fb2In, ' ' + MobiOut +' --ow']) if __name__ == '__main__': main()
subprocess.Popen([Converter])
Отредактировано Novator (Май 19, 2022 21:00:47)
Офлайн
Пример перенаправления потока вывода stdout
>>> import subprocess >>> >>> p = subprocess.Popen(['echo', 'привет'], stdout=subprocess.PIPE) >>> output = p.communicate()[0].decode('utf-8') >>> >>> print(output) привет >>>
Отредактировано py.user.next (Май 20, 2022 00:55:51)
Офлайн
py.user.next, то есть логика запуска у меня в принципе была правильной и ошибка где-то в кавычках или пробелах?
А код:
output = p.communicate()[0].decode('utf-8') print(output)
Отредактировано Novator (Май 20, 2022 06:22:11)
Офлайн
Написал пока так, но чувствую, что это бред. Получается, делать список со строки - это нормально, а писать сразу список в параметре, как я хотел изначально - не нормально
Да, код:
import subprocess, shlex Converter = 'D:/TC/WPI_VOG/Apps/MyHomeLib/converters/fb2converter/fb2c.exe' ConverterIni = 'D:/TC/WPI_VOG/Apps/MyHomeLib/converters/fb2mobi/fb2mobi.toml' Fb2In = 'J:/My_project_programming/Converter/test/FB2' MobiOut= 'J:/My_project_programming/Converter/test/Mobi' def main(): cmd = Converter + ' -c ' + ConverterIni + ' convert --to mobi ' + Fb2In + ' ' + MobiOut +' --ow' args = shlex.split(cmd) p = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) result = p.communicate()[0].decode('UTF-8') print(result) if __name__ == '__main__': main()
Офлайн
Novator
Получается, делать список со строки - это нормально, а писать сразу список в параметре, как я хотел изначально - не нормально
[Converter, '-c', ConverterIni, 'convert', '--to', 'mobi', Fb2In, MobiOut, '--ow']
Офлайн
Дело проясняется, но через print в консоль все выводится красиво и постепенно, а вот в текстовое поле - рывком и все сразу, невзирая на цикл. Обидно
for book in sel_book: logtext = self.txt_console.toPlainText() book = self.path['Fb2In'] + '/' + book p = subprocess.Popen([self.path['Converter'], '-c', self.path['ConverterIni'], 'convert', '--to', 'mobi', book, self.path['MobiOut'], '--ow'], stdout=subprocess.PIPE) result = p.communicate()[0].decode('UTF-8') self.txt_console.setPlainText(logtext + result)
Офлайн
NovatorПолный код скинь.
но через print в консоль все выводится красиво и постепенно, а вот в текстовое поле - рывком и все сразу
Офлайн
fb2mainwindow.py
# -*- coding: utf-8 - * - # Импортируем библиотеки import json import os # import sys # sys нужен для передачи argv в QApplication import subprocess import sys from PyQt5 import QtWidgets, QtCore # from PyQt5.QtGui import QColor # from PyQt5.QtWidgets import QLabel, QMessageBox, QProgressBar from PyQt5.QtWidgets import QFileDialog, QMessageBox from fb2mainwindow import design # Класс главного окна class MainForm(QtWidgets.QMainWindow, design.Ui_MainWindow): # Инициализация окна и обработчики событий def __init__(self): super().__init__() self.check = None self.root_dir = None self.setts = None self.setupUi(self) self.path = self.read_settings()['path'] self.checkboxes = self.read_settings()['checkboxes'] self.other = self.read_settings()['other'] self.btn_open.clicked.connect(self.load_books_in_list) self.lst_book.itemClicked.connect(self.check_item_in_books_list) self.lst_book.setContextMenuPolicy(QtCore.Qt.CustomContextMenu) self.lst_book.customContextMenuRequested.connect(self.context_menu_mainform) self.btn_convert.clicked.connect(self.convert_selected_books) self.checkBox.clicked.connect(lambda checked, button=self.checkBox: self.select_path(button, text='SendMobi')) self.checkBox_2.clicked.connect(lambda checked, button=self.checkBox_2: self.select_path(button, text='ArcFB2')) self.checkBox_3.clicked.connect(lambda checked, button=self.checkBox_3: self.select_path(button, text='ArcMobi')) self.checkBox_4.clicked.connect(lambda checked, button=self.checkBox_4: self.select_path(button, text='HideConverter')) self.btn_set_1.clicked.connect(lambda checked, button=self.txt_set_1: self.select_path(button, mask='fb2c.exe|Converter')) self.btn_set_2.clicked.connect(lambda checked, button=self.txt_set_2: self.select_path(button, mask='*.toml|ConverterIni')) self.btn_set_3.clicked.connect(lambda checked, button=self.txt_set_3: self.select_path(button, mask='^|Fb2In')) self.btn_set_4.clicked.connect(lambda checked, button=self.txt_set_4: self.select_path(button, mask='^|Fb2Out')) self.btn_set_5.clicked.connect(lambda checked, button=self.txt_set_5: self.select_path(button, mask='^|MobiOut')) self.btn_set_6.clicked.connect(lambda checked, button=self.txt_set_6: self.select_path(button, mask='HaoZipC.exe|Arc')) def read_settings(self): self.root_dir = os.path.dirname(sys.modules['__main__'].__file__) with open(self.root_dir + '\\config\\conf.json') as conffile: self.setts = json.load(conffile) return self.setts def load_books_in_list(self): self.lst_book.clear() list_books_fb2in = os.listdir(self.path['Fb2In']) for book in list_books_fb2in: item = QtWidgets.QListWidgetItem() item.setText(book) item.setCheckState(QtCore.Qt.Unchecked) self.lst_book.addItem(item) def context_menu_mainform(self, point): if self.lst_book.count() > 0: menu = QtWidgets.QMenu() menu_selection = menu.addMenu('Selection') sel_all = QtWidgets.QAction('Select all', menu_selection) sel_all.triggered.connect(lambda: self.sel_desell_all('select')) desel_all = QtWidgets.QAction('Deselect all', menu_selection) desel_all.triggered.connect(lambda: self.sel_desell_all('deselect')) inverse = QtWidgets.QAction('Invert selection', menu_selection) inverse.triggered.connect(lambda: self.sel_desell_all('inverse')) menu_selection.addAction(sel_all) menu_selection.addAction(desel_all) menu_selection.addAction(inverse) menu.exec(self.lst_book.mapToGlobal(point)) def sel_desell_all(self, p): items = range(self.lst_book.count()) for index in items: if p == 'select': # выбрать все self.lst_book.item(index).setCheckState(QtCore.Qt.Checked) self.lst_book.item(index).setSelected(True) elif p == 'deselect': # снять все self.lst_book.item(index).setCheckState(QtCore.Qt.Unchecked) self.lst_book.item(index).setSelected(False) elif p == 'inverse': # инвертировать выделение if self.lst_book.item(index).checkState() == QtCore.Qt.Checked: self.lst_book.item(index).setCheckState(QtCore.Qt.Unchecked) self.lst_book.item(index).setSelected(False) else: self.lst_book.item(index).setCheckState(QtCore.Qt.Checked) self.lst_book.item(index).setSelected(True) def check_errors(self): self.check = True def fill_settings(self): self.tabWidget.setCurrentIndex(0) self.txt_set_1.setPlainText(self.path['Converter']) self.txt_set_2.setPlainText(self.path['ConverterIni']) self.txt_set_3.setPlainText(self.path['Fb2In']) self.txt_set_4.setPlainText(self.path['Fb2Out']) self.txt_set_5.setPlainText(self.path['MobiOut']) self.txt_set_6.setPlainText(self.path['Arc']) self.checkBox.setChecked(True) if self.checkboxes['SendMobi'] == "1" else self.checkBox.setChecked(False) self.checkBox_2.setChecked(True) if self.checkboxes['ArcFB2'] == "1" else self.checkBox_2.setChecked(False) self.checkBox_3.setChecked(True) if self.checkboxes['ArcMobi'] == "1" else self.checkBox_3.setChecked(False) self.checkBox_4.setChecked(True) if self.checkboxes['HideConverter'] == "1" \ else self.checkBox_4.setChecked(False) def select_path(self, button, text='', mask=''): if text: self.checkboxes[text] = "1" if button.isChecked() else "0" if mask.split('|')[0] == '^': fname = QFileDialog.getExistingDirectory(self, 'Select folder...', 'D:/') else: fname = QFileDialog.getOpenFileName(self, 'Select file...', 'D:/', mask.split('|')[0])[0] button.setPlainText(fname) self.setts['path'][mask.split('|')[1]] = fname with open(self.root_dir + '\\config\\conf.json', 'w') as f: f.write(json.dumps(self.setts, indent=2)) self.read_settings() @staticmethod def check_item_in_books_list(item): if item.checkState() == QtCore.Qt.Checked: item.setCheckState(QtCore.Qt.Unchecked) else: item.setCheckState(QtCore.Qt.Checked) def convert_selected_books(self): sel_book = [] for index in range(self.lst_book.count()): if self.lst_book.item(index).checkState() == QtCore.Qt.Checked: sel_book.append(self.lst_book.item(index).text()) if not sel_book and self.other['null select'] == "1": for index in range(self.lst_book.count()): sel_book.append(self.lst_book.item(index).text()) elif not sel_book and self.other['null select'] == "0": QMessageBox.critical(self, "Error!", "Not selected file(s)") if sel_book: for book in sel_book: logtext = self.txt_console.toPlainText() book = self.path['Fb2In'] + '/' + book p = subprocess.Popen([self.path['Converter'], '-c', self.path['ConverterIni'], 'convert', '--to', 'mobi', book, self.path['MobiOut'], '--ow'], stdout=subprocess.PIPE) result = p.communicate()[0].decode('UTF-8') self.txt_console.setPlainText(logtext + result) print('Обработка завершена')
Отредактировано Novator (Май 21, 2022 15:31:42)
Офлайн
Fb2Converter.py:
import sys from PyQt5 import QtWidgets from fb2mainwindow.mainform import MainForm def run(): app = QtWidgets.QApplication(sys.argv) window = MainForm() window.show() window.check_errors() window.fill_settings() sys.exit(app.exec_()) run()
Офлайн
conf.json:
{ "path": { "Converter": "D:/TC/WPI_VOG/Apps/MyHomeLib/converters/fb2converter/fb2c.exe", "ConverterIni": "D:/TC/WPI_VOG/Apps/MyHomeLib/converters/fb2mobi/fb2mobi.toml", "Fb2In": "J:/My_project_programming/Converter/test/FB2", "Fb2Out": "J:/My_project_programming/Converter/test/FB2Final", "MobiOut": "J:/My_project_programming/Converter/test/Mobi", "Arc": "D:/TC/TC_VOG/Plugins/Arc/HZ/HaoZipC.exe" }, "checkboxes": { "SendMobi": "1", "ArcFB2": "0", "ArcMobi": "0", "HideConverter": "0", "VisibleTestBeforeRename": "1" }, "other": { "null select": "0" } }
Офлайн