Я пытался добавить свой вывод команды во временный файл в python, а затем выполнить некоторые операции. Не удалось добавить данные во временный файл. Любая помощь приветствуется! Мой пример кода выглядит следующим образом.

Получаю такую ​​ошибку.

с open(temp1, 'r') как f: TypeError: ожидаемая строка, байты или объект os.PathLike, а не _TemporaryFileWrapper

import tempfile
import os
temp1 = tempfile.NamedTemporaryFile()
os.system("echo Hello world | tee temp1")
with open(temp1 , 'r') as f:
    a = f.readlines()[-1]
    print(a)
3
lilly m 20 Сен 2022 в 21:55
2
NamedTemporaryFile уже возвращает открытый файловый объект, нет необходимости open() это снова
 – 
rdas
20 Сен 2022 в 21:58
temp1 — это имя переменной Python, а не имя файла. Значение этой переменной имеет атрибут name, который содержит фактическое имя файла.
 – 
chepner
20 Сен 2022 в 22:10
Даже когда я получил доступ через атрибут имени ``` с open(temp1.name, 'r') как f:``` , он все еще не работает. проблема заключается в добавлении/передаче данных во временный файл. Можно ли этого добиться каким-то другим способом?
 – 
lilly m
20 Сен 2022 в 22:25

5 ответов

import tempfile
import os

# Opening in update-text mode to avoid encoding the data written to it
temp1 = tempfile.NamedTemporaryFile("w+")
# popen opens a pipe from the command, allowing one to capture its output
output = os.popen("echo Hello world")

# Write the command output to the temporary file
temp1.write(output.read())

# Reset the stream position at the beginning of the file, if you want to read its contents
temp1.seek(0)
print(temp1.read())

Ознакомьтесь с subprocess.Popen для более эффективного взаимодействия подпроцессов. .

1
Ulisse Bordignon 20 Сен 2022 в 22:30

Попробуй это :

import tempfile
import os

with tempfile.NamedTemporaryFile(delete=False) as temp_file:
    temp_file.close()

    os.system("echo Hello world | tee temp1")

    with open(temp_file.name, temp_file.mode) as new_temp_file:
        #### APPEND HERE YOUR STUFF
        new_temp_file.seek(0)
        for line in new_temp_file.readlines():
            print(line)
0
abokey 20 Сен 2022 в 22:27

Что бы вы ни пытались сделать, это неправильно. Похоже, вы пытаетесь заставить системный вызов записать в файл, а затем хотите прочитать этот файл в своем коде Python. Вы создаете временный файл, но ваш системный вызов выполняет запись в файл со статическим именем 'temp1', а не во временный файл, который вы открыли. Поэтому неясно, хотите ли вы/нужно использовать вычисляемое имя временного файла или допустимо ли использование temp1. Самый простой способ исправить ваш код, чтобы он делал то, что, как я думаю, вы хотите, выглядит следующим образом:

import os
os.system("echo Hello world | tee temp1")
with open('temp1' , 'r') as f:
    a = f.readlines()[-1]
    print(a)

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

import tempfile
import os

with tempfile.TemporaryDirectory() as dir:
    tempfile = os.path.join(dir, "temp1")
    os.system("echo Hello world /tmp > " + tempfile)
    with open(tempfile) as f:
        buf = f.read()

print(buf)

Этот метод имеет дополнительное преимущество автоматической очистки для вас.

ОБНОВЛЕНИЕ: теперь я видел ответ @UlisseBordingnon. Это лучшее решение в целом. Использование os.system() не рекомендуется. Я бы пошел немного другим путем, используя модуль subprocess, но то, что они предлагают, является на 100% действительным и безопасным для потоков и безопасности. Думаю, я оставлю свой ответ здесь, так как, возможно, вам или другим читателям нужно использовать os.system() или иным образом заставить процесс оболочки, который вы выполняете, записывать непосредственно в файл.

0
CryptoFool 20 Сен 2022 в 22:53
Установка temp на «temp1» сделает файл обычным. Я хочу использовать временный файл в этом случае. например, сохранить в нем вывод команды и выполнить некоторые операции с данными. это может быть достигнуто другим способом?
 – 
lilly m
20 Сен 2022 в 22:15
Я заметил, что вы говорите, что хотите «добавить» файл. Это говорит о том, что у вас будет файл, который уже существует и в нем что-то есть. Ни один из ответов пока не касается этого, включая мой. Вы действительно имели в виду «записать», а не «дополнить»? Если вы действительно имели в виду «дополнить», то вам не нужно делать ничего из этого, поскольку файл уже существует и поэтому уже определяет путь, с которым вы хотите работать.
 – 
CryptoFool
20 Сен 2022 в 22:47
Я упомянул добавление, но на самом деле я имел в виду для письма. Если я хочу сохранить результат команды во временном файле и выполнить над ним операции позже.
 – 
lilly m
20 Сен 2022 в 23:01

Как предлагали другие, вы должны использовать модуль subprocess вместо os.system. Однако из subprocess вы можете использовать самый последний интерфейс (и самым последним, я полагаю, что это было добавлено в Python 3.4) subprocess.run.

Преимущество использования .run заключается в том, что вы можете передать любой файлоподобный объект в stdout, и поток stdout автоматически перенаправит на этот файл.

import tempfile
import subprocess

with tempfile.NamedTemporaryFile("w+") as f:
    subprocess.run(["echo", "hello world"], stdout=f)
    
    # command has finished running, let's check the file
    f.seek(0)
    print(f.read())
    # hello world
0
Cameron Riddell 21 Сен 2022 в 16:00

В зависимости от ваших потребностей, если вы печатаете свой вывод, более быстрый способ, но, возможно, не совсем то, что вы ищете, - это перенаправить вывод в файл на уровне командной строки Пример (egfile.py):

import os

os.system("echo Hello world")

На командном уровне вы можете просто сделать:

python egfile.py > file.txt

Вывод файла будет перенаправлен в файл, а не на экран.

-1
ilival 20 Сен 2022 в 23:00
ОП явно хочет записать в файл выполнение команды, а затем прочитать результат в том же бите кода. Этот ответ бесполезен для решения этой проблемы.
 – 
CryptoFool
20 Сен 2022 в 23:07