LINUX.ORG.RU

Python умеет как bash?

 , , ,


0

3

В bash можно направить вывод в разные потоки.

echo test >&1
echo error >&2
echo data >&3

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

testscript.sh 1> filename.text 2> filename.errors.log 3> filename.data

В python, выполнив команду операционной системы через subprocess, можно получить и stdout и stderr. Можно ли получить также другие потоки если таковые есть?

Перемещено hobbit из general

★★★★★

https://docs.python.org/3/library/subprocess.html

ты ведь тут был, да? ты ведь читал, да?

subprocess.run(args, *, stdin=None, input=None, stdout=None, stderr=None, capture_output=False, shell=False, cwd=None, timeout=None, check=False, encoding=None, errors=None, text=None, env=None, universal_newlines=None, **other_popen_kwargs)

other_popen_kwargs

class subprocess.Popen(args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False, cwd=None, env=None, universal_newlines=None, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=(), *, group=None, extra_groups=None, user=None, umask=-1, encoding=None, errors=None, text=None, pipesize=-1, process_group=None)

pass_fds

(питон не знаю и не признаю, так что, не спрашивай 🤡)

aol ★★★★★
()
Последнее исправление: aol (всего исправлений: 1)
Ответ на: комментарий от aol

чо у вас всех так горит со сраных эмоджи, которые режутся одной строкой в адблоке?
нахер их вообще впиливали?

// не поленился, отключил ublock, поставил клоуна, включил обратно.

annerleen_temp
()
Ответ на: комментарий от aol

Насколько я смог понять, pass_fds для вывода потоков. Мне же желательно получить не смешивая и не для вывода а для использования.

Впрочем, не спрашивать – так не спрашивать.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

Насколько я смог понять, pass_fds для вывода потоков

pass_fds — ровно для того, что отражено в названии. То есть для передачи процессу файловых дескрипторов. А что ты с ними будешь делать, решать тебе.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Похоже мои способности к формированию поискового запроса ненамного лучше знаний питона. Не приведёшь пример получения потока и записи его в переменную?

sin_a ★★★★★
() автор топика
Ответ на: комментарий от sin_a

Тут нужны знания POSIX, а не питона. Вообще это не самая тривиальная задача — для stdout и stderr в питоне есть удобный сахар, а для произвольных fd нет, нужно писать ровно такой же код, который ты бы написал на Си.

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 1)
Ответ на: комментарий от sin_a

Если ты хочешь получить от программы больше одного потока одновременно, и каждый получить в переменную, тебе придётся развлекаться с select. Так что да, лучше временные файлы.

intelfx ★★★★★
()
Ответ на: комментарий от intelfx

Да уже и про bash прочёл что это не предусмотрено, но некоторые развлекаются переопределяя IFS на перевод строки (наверно у них вывод из одной таковой). Но думал что питон-то – настоящий язык программирования. Не, здесь он понадобился не из за этого, но, думаю, раз уж есть то надо использовать.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от intelfx

зачем select? и какого рода файлы, для них вообще select будет работать?

можно по потоку на обработку каждого файла сделать, а внутри какие-то свои очереди навернуть хоть с async/await и без низкоуровневых select’ов

ei-grad ★★★★★
()
import os
import subprocess

# Создаем временные файлы для перенаправления потоков
stdout_file = 'filename.text'
stderr_file = 'filename.errors.log'
fd3_file = 'filename.data'

# Открываем файлы для записи
with open(stdout_file, 'w') as stdout, open(stderr_file, 'w') as stderr, open(fd3_file, 'w') as fd3:
    # Получаем файловый дескриптор для fd3
    fd3_fd = fd3.fileno()
    
    # Команда для выполнения
    command = ['./testscript.sh']
    
    # Запускаем процесс
    proc = subprocess.Popen(
        command,
        stdout=stdout,
        stderr=stderr,
        pass_fds=[fd3_fd]
    )
    
    # Дожидаемся завершения процесса
    proc.wait()
ei-grad ★★★★★
()
Ответ на: комментарий от ei-grad

Спасибо, очень интересно.

Это тоже вывод в файлы, в переменную наверно действительно только через сокеты, как здесь сказали. Правда есть ещё вариант, запускать отдельный скрипт и в него на stdin подавать данные. Но я пока вообще пошёл по другому пути.

sin_a ★★★★★
() автор топика
Ответ на: комментарий от ei-grad

зачем select?

Чтобы не словить взаимоблокировку при поочерёдном чтении из нескольких потоков. Та же проблема, что описана в subprocess.Popen.communicate().

и какого рода файлы

os.pipe()

intelfx ★★★★★
()
Последнее исправление: intelfx (всего исправлений: 2)
Ответ на: комментарий от ei-grad

ChatGPT:

В этом примере мы создадим пайп, передадим файловые дескрипторы дочерним процессам и обеспечим взаимодействие между ними через этот пайп.

Для начала, создадим скрипт producer.py, который будет писать данные в пайп:

# producer.py
import os
import sys

def main():
    pipe_out = int(sys.argv[1])

    # Открытие файлового объекта для записи
    with os.fdopen(pipe_out, 'w') as pipe_write:
        pipe_write.write("Hello from producer!\n")
        pipe_write.write("This is a test.\n")

if __name__ == "__main__":
    main()

Затем создадим скрипт consumer.py, который будет читать данные из пайпа:

# consumer.py
import os
import sys

def main():
    pipe_in = int(sys.argv[1])

    # Открытие файлового объекта для чтения
    with os.fdopen(pipe_in, 'r') as pipe_read:
        for line in pipe_read:
            print(f"Consumer received: {line.strip()}")

if __name__ == "__main__":
    main()

Теперь создадим основной скрипт, который будет создавать пайп, запускать producer.py и consumer.py, и передавать им соответствующие дескрипторы:

import os
import subprocess

def main():
    # Создание пайпа
    pipe_read, pipe_write = os.pipe()

    # Команды для выполнения
    producer_cmd = ['python3', 'producer.py', str(pipe_write)]
    consumer_cmd = ['python3', 'consumer.py', str(pipe_read)]

    # Запуск producer процесса
    producer_proc = subprocess.Popen(
        producer_cmd,
        pass_fds=[pipe_write]
    )

    # Запуск consumer процесса
    consumer_proc = subprocess.Popen(
        consumer_cmd,
        pass_fds=[pipe_read]
    )

    # Закрытие пайпов в родительском процессе
    os.close(pipe_read)
    os.close(pipe_write)

    # Ожидание завершения процессов
    producer_proc.wait()
    consumer_proc.wait()

if __name__ == "__main__":
    main()

В этом примере:

  1. Основной скрипт создает пайп с помощью os.pipe(), который возвращает два файловых дескриптора: один для чтения, другой для записи.
  2. Запускаются два дочерних процесса: producer.py и consumer.py, которым передаются соответствующие дескрипторы пайпа через pass_fds.
  3. В producer.py открывается файловый объект для записи и записываются данные в пайп.
  4. В consumer.py открывается файловый объект для чтения и данные читаются из пайпа.
  5. Основной скрипт закрывает дескрипторы пайпа в родительском процессе и ожидает завершения дочерних процессов.

Таким образом, мы создали пайп между двумя программами и передали файловые дескрипторы с помощью pass_fds.

ei-grad ★★★★★
()

Привет! Посмотрел https://www.youtube.com/watch?v=qrJkY-hjjIM и понял, что разрабы питона готовят в версии 3.13 армагеддон сравнимый с переходом со второй версии на третью. Они собираются удалить GIL и сломать расширения на других языках. Например, перестанет работать математика и графика написанная на С++, типа NumPy. Что делать? Разрабам рекомендуют переписать их код, а юзерам пользоваться старыми версиями. Помнится, Виндоус не дождалась переписывальщиков и, чтобы не потерять юзеров, поместила в своё ядро коды совместимости с сотнями старых программ. Не опухнет ли интерпретатор питона от подобного решения?

anonymous
()