Найти - Пользователи
Полная версия: Запуск внешней программы с параметрами
Начало » Python для новичков » Запуск внешней программы с параметрами
1 2
Novator
Доброго времени суток!
Подскажите, как вызвать внешнюю программу с параметрами, и, если возможно, перенаправить ее лог в текстовое поле?
Вот, например, на 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])
Вывод лога работы идет в консоль, а вот запуска с параметрами нет. Подскажите, в чем я ошибаюсь? Или может, есть способ проще? Пробовал записать это в батник и вызывать его - работает, но ведь это же еще тот костыль….
py.user.next
Пример перенаправления потока вывода stdout
  
>>> import subprocess
>>> 
>>> p = subprocess.Popen(['echo', 'привет'], stdout=subprocess.PIPE)
>>> output = p.communicate()[0].decode('utf-8')
>>> 
>>> print(output)
привет
 
>>>
Novator
py.user.next, то есть логика запуска у меня в принципе была правильной и ошибка где-то в кавычках или пробелах?
А код:
 output = p.communicate()[0].decode('utf-8')
print(output)
мне выводит None (без декодирования) или b' ' с декодированием, то есть посмотреть и понять где ошибка в переданной строке параметров не получится
Novator
Написал пока так, но чувствую, что это бред. Получается, делать список со строки - это нормально, а писать сразу список в параметре, как я хотел изначально - не нормально
Да, код:
 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()
py.user.next
Novator
Получается, делать список со строки - это нормально, а писать сразу список в параметре, как я хотел изначально - не нормально
[Converter, '-c', ConverterIni, 'convert', '--to', 'mobi', Fb2In, MobiOut, '--ow']
Novator
Дело проясняется, но через 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)
py.user.next
Novator
но через print в консоль все выводится красиво и постепенно, а вот в текстовое поле - рывком и все сразу
Полный код скинь.
Novator
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
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()
Novator
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"
  }
}
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB