Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
problem with readline()
#1
Hi,
I just start to learn pyhton. I'm using 3.7.2 on windows. I have text files which contain full paths of video files, like:
video.lst:
Quote:c:\videos\video1.mp4
c:\videos\video2.mp4
c:\videos\video3.mp4
...


I want to find out how they are encoded with ffprobe. With the full given path of the video file everything works fine:

import os
import subprocess

filePath = r"c:\videos\video1.mp4"

ffprobeResult = subprocess.run(['ffprobe', '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=codec_name', '-of', 'default=noprint_wrappers=1:nokey=1', filePath], universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

print(ffprobeResult.stdout)
What doesn't work:
import os
import subprocess

with open(r"c:\video\video.lst","r") as f:
    filePath = 'r"' + str(f.readline()) + '"'
    
ffprobeResult = subprocess.run(['ffprobe', '-v', 'error', '-select_streams', 'v:0', '-show_entries', 'stream=codec_name', '-of', 'default=noprint_wrappers=1:nokey=1', filePath], universal_newlines=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

print(ffprobeResult.stdout)
It returns:
r"c:\videos\video1.mp4
"
:Invalid argument.

When I change it to
filePath = 'r"' + str(f.readline(18)) + '"'
it works again (18: the bytes of the path). readline seems to add a new line. Does anyone know how to change this or has something else up one's sleeve?

Cheers
Reply
#2
Try
filepath = f.readline().strip()
Reply
#3
readline reads the end of line character. You can remove it with f.readline().strip(). That should be all you need. You shouldn't need the 'r"' and the str.
Craig "Ichabod" O'Brien - xenomind.com
I wish you happiness.
Recommended Tutorials: BBCode, functions, classes, text adventures
Reply
#4
It's not broken, readline does not remove newline.

In [21]: import io                                                                                                          

In [22]: io.TextIOWrapper.readline?                                                                                         
Signature: io.TextIOWrapper.readline(self, size=-1, /)
Docstring:
Read until newline or EOF.

Returns an empty string if EOF is hit immediately.
Type:      method_descriptor
The returned object from open() is a io.TextIOWrapper and io.BufferedReader in binary mode. All this objects inherits from io.IOBase, which is also a iterator (__next__ method is present). This method iterates one line by calling it.

This means, you can use the returned object from open direct in a for loop:

with open('some_file') as fd:
    for line in fd:
        print(line) # \n is still there!!!
To get rid of the white space (newline is also by definition a white space), use the method strip().


with open('some_file') as fd:
    for line in fd:
        print(line.strip())
        # white spaces on the left
        # and right side are removed
Instead of using subprocess.run, you can use subprocess.check_output.

from subprocess import check_output


with open('some_file') as fd:
    for line in fd:
        file = line.strip()
        result = check_output(['echo', file], encoding='utf8')
        # echo > file
        print(result)
To be more flexible, write small functions. Each function should solve one task.

from pathlib import Path


def read_video_list(file):
    with open(file) as fd:
        for line in fd:
            path = Path(line.strip())
            if path.exists() and path.is_file():
                # path exists and is a file
                # THIS DOES NOT GUARANTEE THAT YOU HAVE READ PERMISSION
                video_codec = video_info(str(path))
                # path is a Path object and must be converted to a
                # str, if you want to add this to the command
                print(path, '->', video_codec) # you can make an own function to print this out


def video_info(video_file):
    cmd = [
        'ffprobe', '-v', 'error', '-select_streams',
        'v:0', '-show_entries', 'stream=codec_name',
        '-of', 'default=noprint_wrappers=1:nokey=1',
        video_file,
    ]
    return check_output(cmd, encoding='utf8').rstrip()
    # rstrip, to remove the newline on the right side
For example, I did not made a function to print the data.
This should be in another function, so that you can exchange it independently.
In this case, the video_info should return both, codec_info and path.

Take also a closer look to pathlib.
In this example Path is just used as a shortcut. Otherwise I had to use os.path.exists and os.path.isfile.
Almost dead, but too lazy to die: https://sourceserver.info
All humans together. We don't need politicians!
Reply
#5
Thank you very much for your quick replies/explanations. I'll try them out tomorrow.
Reply
#6
Also you do not need stdout=subprocess.PIPE, stderr=subprocess.STDOUT in run().
Can use capture_output=True or can also use check_output() as @DeaD_EyE do.

Here is a test,code is formatted with black so i don't need to do that work,can aslo just use it online Black Playground
import os
import subprocess

with open('video_lst.txt') as f:
    for video_path in f:
        video_path = video_path.strip()
        ffprobeResult = subprocess.run(
            [
                "ffprobe",
                "-v",
                "error",
                "-select_streams",
                "v:0",
                "-show_entries",
                "stream=codec_name",
                "-of",
                "default=noprint_wrappers=1:nokey=1",
                video_path,
            ],
            capture_output=True, text=True
        )
        result = ffprobeResult.stdout.strip()
        print('-' * 15)
        print(f'Video {ffprobeResult.args[-1]} has encoding: {result}') 
Output:
Video G:\1_youtube\planet.mkv has encoding: h264 --------------- Video G:\1_youtube\sky_walk.mkv has encoding: h264
Reply
#7
Thank you very much. Works like a charm :)
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Pyserial Readline() conversion to array bprosman 1 1,817 Apr-11-2023, 12:44 AM
Last Post: deanhystad
  Greek letters with .readline() and tkinter KinkgOfKeks 7 1,628 Mar-24-2023, 05:13 PM
Last Post: deanhystad
Star Pyserial not reading serial.readline fast enough while using AccelStepper on Arduino MartyTinker 4 3,865 Mar-13-2023, 04:02 PM
Last Post: deanhystad
  readline.parse_and_bind() does not work in start-up script of Python interpreter zzzhhh 0 1,473 Jan-18-2022, 11:05 AM
Last Post: zzzhhh
  readline inside and outside functions paul18fr 2 2,001 May-20-2021, 01:15 PM
Last Post: csr
  TypeError: file must have 'read' and 'readline' attributes hobbyist 6 10,663 Jun-12-2020, 05:12 PM
Last Post: DreamingInsanity
  readline() and readlines() rpaskudniak 9 29,935 Nov-21-2017, 07:39 PM
Last Post: metulburr
  Empty variable when using print before readline fstefanov 3 3,607 Oct-23-2017, 02:22 AM
Last Post: fstefanov
  pySerial .readline() help AlexSneedMiller 1 14,433 Jan-23-2017, 01:16 PM
Last Post: j.crater
  How can I use GNU readline when the value of sys.stdin has been changed? thePhysicist8 6 7,002 Dec-30-2016, 10:09 AM
Last Post: Skaperen

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020