Как вызвать сценарий Perl с парой аргументов с тегом html из сценария Python, используя Subprocess/shell?

В скрипте Python у меня есть функция, которая выглядит следующим образом:

def NotifierFunc(Mail, Ticket_Num, Open_DtTime):
    cmd = "/home/path/MyPerlScript.pl --channel 'MyChannel' --userid 'itsme' --message 'Hello <at>"+Mail+"<at> : The ticket <a href='`echo 'http://snview/'"+Ticket_Num+">`echo "+Ticket_Num+"`</a> is not closed for more than 72 hours : Open since "+Open_DtTime+" IST. Please close asap.' "
    print(cmd)
    subprocess.Popen(cmd, shell= True, stout=subprocess.PIPE)

Что он печатает:

/home/path/MyPerlScript.pl --channel 'MyChannel' --userid 'itsme' --message 'Hello <at>[email protected]<at> : The ticket <a href='`echo 'http://snview/'INC23548>`echo INC23548`</a> is not closed for more than 72 hours : Open since 4-APR-2024 12:30:40 IST. Please close asap.' 

Эта команда не выполняется успешно в оболочке главным образом потому, что сообщение (все, что передается после «--message», заключено в одинарные кавычки) или, по крайней мере, я так думаю. Когда я помещаю это в двойные кавычки, скрипт Python выдает синтаксическую ошибку. Когда я помещаю все значение cmd в одинарную кавычку или строку документа quote(''') и содержимое --message в двойную кавычку, это также приводит к синтаксической ошибке.

Если я запускаю команду cmd непосредственно в командной строке Linux (с содержимым --message в двойных кавычках), все работает нормально:

> Mail = "[email protected]"
> Ticket_Num = "INC23548"
> Open_DtTime = "14-APR-2024 12:30:40"
> /home/path/MyPerlScript.pl --channel 'MyChannel' --userid 'itsme' --message "Hello <at>$Mail<at> : The ticket <a href='`echo 'http://snview/'$Ticket_Num >`echo $Ticket_Num`</a> is not closed for more than 72 hours : Open since $Open_DtTime IST. Please close asap."

Теперь мой вопрос заключается в том, как я могу передать все это значение cmd в подпроцесс, чтобы содержимое «--message» могло быть отображено правильно, или как я могу поместить содержимое «--message» в двойные кавычки и заставить его работать.

Обратите внимание, что если я передам cmd, как показано ниже, он работает нормально, но у него нет гиперссылки на номер билета. Но мне нужна гиперссылка.

cmd = "/home/path/MyPerlScript.pl --channel 'MyChannel' --userid 'itsme' --message 'Hello <at>"+Mail+"<at> : The ticket +Ticket_Num+" is not closed for more than 72 hours : Open since "+Open_DtTime+" IST. Please close asap.' "

Я также пробовал помещать переменные в {} и пробовал различные комбинации кавычек. Пока ничего не работает. Я использую Python 3.10

Чтобы прояснить, как должна выглядеть ожидаемая команда, можете ли вы показать, как можно вызвать сценарий Perl из командной строки? Это может помочь нам понять, чего вы пытаетесь достичь с помощью сценария Python.

Håkon Hægland 28.04.2024 18:59

возможно, получите строку, отображаемую print(cmd), и попробуйте запустить ее непосредственно в shell, чтобы проверить, правильна ли она. Как по мне, у вас есть ошибки в HTML - у них есть ', что, возможно, должно быть \'. Вы также можете показать эту строку. Возможно, понадобится еще \\" или \\'

furas 28.04.2024 21:02

всегда помещайте ПОЛНОЕ сообщение об ошибке (начиная со слова «Traceback») в вопросе (не в комментариях) в виде текста (не скриншота и не ссылки на внешний портал). В полной версии ошибки/трассировки есть и другая полезная информация.

furas 28.04.2024 21:03

Кстати: иногда проще создать только строку с сообщением, а затем поместить ее в полную строку с помощью cmd

furas 28.04.2024 21:09

@furas: Да, я пробовал печатать — печатается нормально, за исключением HTML-части. Я также пробовал запустить его в командной строке Linux. Просто отредактировал свой вопрос, чтобы добавить именно то, что я запускал из командной строки. Ошибка просто означает синтаксическую ошибку. Позвольте мне попытаться указать именно то, что он показывает, когда я печатаю с помощью скрипта Python.

instinct246 28.04.2024 21:10

@HåkonHægland: добавлено то, что я запускаю из командной строки Linux. Спасибо

instinct246 28.04.2024 21:11

покажите этот отпечаток, о котором идет речь (не в комментариях) - возможно, нужно только добавить \ или \\

furas 28.04.2024 21:12

честно говоря, я не понимаю, почему вы используете echo в коде Python. Почему бы не помещать значения непосредственно в строку в Python.

furas 28.04.2024 21:14

показать также результат print( cmd ). ИЛИ создайте minimal working code с примерами данных, чтобы мы могли просто скопировать и запустить его.

furas 28.04.2024 21:18

@furas: только что добавил результат печати (cmd)

instinct246 28.04.2024 21:22

во-первых: вам не нужен echo в коде. Во-вторых: поскольку сообщение находится ' ', вам нужно \' внутри этого сообщения href=\'.... \' - полное сообщение f" .... --message 'Hello <at>{Mail}<at> : The ticket <a href=\'http://snview/{Ticket_Num}\'>{Ticket_Num}</a> is not closed for more than 72 hours : Open since {Open_DtTime} IST. Please close asap.'"

furas 28.04.2024 21:28

1) Если у вас нет (неизбежной) необходимости в оболочке, не используйте ее. 2) Для этого длинного «сообщения» я сначала готовил строку, а затем использовал ее для формирования команды. (3) В этом «сообщении» происходит слишком много всего. Почему обратные кавычки? Почему эхо? Так много цитат, даже ' внутри ' (4) В новых версиях Python можно использовать run вместо Popen

zdim 28.04.2024 21:43
Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
1
12
85
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

subprocess.Popen принимает список в качестве первого аргумента, что упрощает обработку и интерполяцию строк. Вместо того, чтобы экранировать некоторые последовательности, потому что другие содержат кавычки или двойные кавычки, разделите их, как в примерах из документации.

Я создал тестовый сценарий Perl, который просто печатает каждый аргумент для запуска из Python.

#!/usr/bin/env perl

use feature qw(say);

say for @ARGV;

И выполнить его из Python вот так

#!/usr/bin/env python

import subprocess
import sys


def NotifierFunc(Mail, Ticket_Num, Open_DtTime):
    cmd = [
        "./main.pl",
        "--channel",
        "MyChannel",
        "--userid",
        "itsme",
        "--message",
        f'Hello <at>{Mail}<at> : The ticket <a href = "http://snview/{Ticket_Num}">{Ticket_Num}</a>'
        f" is not closed for more than 72 hours : Open since {Open_DtTime} IST. Please close asap.",
    ]

    subprocess.Popen(cmd, shell=False, stdout=sys.stdout)


if __name__ == "__main__":
    NotifierFunc("[email protected]", "INC23548", "14-APR-2024 12:30:40")

Обратите внимание, что я установил shell на False и изменил stdout, чтобы проверить ваш пример и посмотреть, что он напечатает. Я также внес некоторые другие изменения, например, удалил обратные кавычки (которые порождают еще один подпроцесс в Perl и вызывают echo) и вместо этого использую f-строки.

Кажется, это печатает все аргументы, как и ожидалось.

› python main.py
--channel
MyChannel
--userid
itsme
--message
Hello <at>[email protected]<at> : The ticket <a href = "http://snview/INC23548">INC23548</a> is not closed for more than 72 hours : Open since 14-APR-2024 12:30:40 IST. Please close asap.

Спасибо за ваш ответ. Я попробовал это первым, так как это выглядит очень аккуратно, однако возникла ошибка: «Использование неинициализированного значения $channel в конкатенации (.) или строки в /home/path/MyPerlScript.pl». Не уверен, что я делаю неправильно – возможно, что-то связано с тем, как написан Perl-скрипт. Если я печатаю cmd внутри Python, он просто печатает список.

instinct246 29.04.2024 13:17
Ответ принят как подходящий

Во-первых: вам не нужен echo в Python, потому что вы помещаете непосредственно значения, а не переменные оболочки.

Во-вторых: поскольку сообщение находится в ' ', внутри этого сообщения вам нужно использовать \', чтобы правильно его отформатировать.

Но для shell было бы лучше разместить ссылку " " внутри сообщения, которое находится в ' ' - '..."..."...' - и поскольку вся строка находится в " ", поэтому внутри строки вам понадобится \"
лайк " '...\"...\"...' "

f" ... --message 'Hello <at>{Mail}<at> : The ticket <a href=\"http://snview/{Ticket_Num}\">{Ticket_Num}</a> is not closed for more than 72 hours : Open since {Open_DtTime} IST. Please close asap.'"

Или вы должны вставить сообщение " " и внутри сообщения использовать ' ' - - "...'...'..." - и снова нужно \", но в другом месте
лайк " \"...'...'...\" "

f" ... --message \"Hello <at>{Mail}<at> : The ticket <a href='http://snview/{Ticket_Num}'>{Ticket_Num}</a> is not closed for more than 72 hours : Open since {Open_DtTime} IST. Please close asap.\""

Полный код для теста:

import subprocess

Mail = "[email protected]"
Ticket_Num = "INC23548"
Open_DtTime = "14-APR-2024 12:30:40"

cmd = f"./MyPerlScript.pl \
--channel 'MyChannel' \
--userid 'itsme' \
--message 'Hello <at>{Mail}<at> : The ticket <a href=\"http://snview/{Ticket_Num}\">{Ticket_Num}</a> is not closed for more than 72 hours : Open since {Open_DtTime} IST. Please close asap.'"
print(cmd)

subprocess.Popen(cmd, shell= True)#, stout=subprocess.PIPE)

Я согласен, что использование Echo или обратного тика никогда не было хорошей идеей - сначала я использовал строку формата - она ​​не работала из-за неправильных escape-символов, на которые вы указали. Я погуглил и нашел где-то - так что просто попробовал. Мне помогло не первое решение (поскольку сообщение все еще приходило в одинарных кавычках), а второе решение. f" ... --message \"Привет <at>{Mail><at> : Заявка <a href='snview{Ticket_Num}'>{Ticket_Num}</a> не закрыта более чем 72 часа: открыто с {Open_DtTime} IST. Пожалуйста, закройте как можно скорее.»» Большое спасибо!

instinct246 29.04.2024 13:12

Я менял кавычки в ответе - возможно, вы пробовали старую версию :)

furas 29.04.2024 13:15

Нет, нет, я имел в виду, что вариант 1, указанный ниже, у меня не сработал : f" ... --message 'Hello <at>{Mail}<at> : Билет <a href=\"snview{ Ticket_Num}\">{Ticket_Num</a> не закрыт более 72 часов: открыт с {Open_DtTime} IST. Пожалуйста, закройте как можно скорее.'" Вариант 2 сработал.

instinct246 29.04.2024 13:23

Другие вопросы по теме