Python Forum

Full Version: which is "better" (or more Pythonic)?
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
i have a little function that i am considering whether or not i should use a variable for some intermediate data:

form 1:
    ...
    with Popen(cmd,stdout=PIPE,universal_newlines=all(isinstance(x,str)for x in cmd)) as p:
        return p.stdout.read().splitlines()
or

form 2:
    ...
    un = all(isinstance(x,str)for x in cmd))
    with Popen(cmd,stdout=PIPE,universal_newlines=un) as p:
        return p.stdout.read().splitlines()
should i use the extra variable or not? i'm sure it would slow things down a minuscule undetectable amount.

i did indent the above code by 4 more spaces than it shows in the preview.
https://docs.python.org/3/library/subpro...cess.Popen
Quote:If encoding or errors are specified, or text is true, file objects for stdin, stdout and stderr are opened in text mode using the specified encoding and errors or the io.TextIOWrapper default. The universal_newlines argument is equivalent to text and is provided for backwards compatibility. By default, file objects are opened in binary mode.

I like the second example. If you use it, give it a better name Tongue
do you have a suggestion for a better name? for variables that are needed for a very short range i like to keep them short. for example, in small loops i like to use "x" as the index or "x" and "y" if there are 2 loops nested.
The whole thing seems unpythonic to me. If true, the universal_newline argument indicates that the subprocess' streams should be opened in text mode. Why link this to the fact that the command's arguments have the python type 'str'? This is an unpythonic use of types. Also note that isinstance() should be rarely used in pythonic code.
This should do the same:
with Popen(cmd, stdout=PIPE, encoding='utf8', errors='ignore') as p:
    return p.stdout.read().splitlines()
I use mostly run() now when using subprocess.
subprocess Wrote:The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle.
For more advanced use cases, the underlying Popen interface can be used directly.
import subprocess

output = subprocess.run(['ping', 'google.com'], text=True, capture_output=True)
print(output.stdout)
Output:
Pinging google.com [172.217.21.174] with 32 bytes of data: Reply from 172.217.21.174: bytes=32 time=53ms TTL=52 Reply from 172.217.21.174: bytes=32 time=74ms TTL=52 Reply from 172.217.21.174: bytes=32 time=43ms TTL=52 Reply from 172.217.21.174: bytes=32 time=84ms TTL=52 Ping statistics for 172.217.21.174: Packets: Sent = 4, Received = 4, Lost = 0 (0% loss), Approximate round trip times in milli-seconds: Minimum = 43ms, Maximum = 84ms, Average = 63ms
subprocess Wrote:If encoding or errors are specified, or text is true, file objects for stdin, stdout and stderr
are opened in text mode using the specified encoding and errors or the io.TextIOWrapper default.
The universal_newlines argument is equivalent to text and is provided for backwards compatibility.
By default, file objects are opened in binary mode.
(Nov-16-2019, 06:43 AM)Gribouillis Wrote: [ -> ]The whole thing seems unpythonic to me. If true, the universal_newline argument indicates that the subprocess' streams should be opened in text mode. Why link this to the fact that the command's arguments have the python type 'str'? This is an unpythonic use of types. Also note that isinstance() should be rarely used in pythonic code.
see DeaD_EyE's quote. see the sentence after the one he underlined. By default, file objects are opened in binary mode. and that's what i see happening.

as for types, i am using byte strings more and more now that i do all in only Python3 and more stuff gives my bytes to work with. so when i have functions or sections of code (that eventually become functions) taking some string and resulting in some string, i try to make it str->str and bytes->bytes as much as i can. if i'm using this code/function where bytes are being used, i want to be consistent. i don't want to have to always be converting str back to bytes.

i got used to using Popen() instead of run() because most of my uses involve parallelism which run() does not give me since it waits for the process to finish. of course, there are these cases where i do want to wait for completion. so out of habit i do use Popen(). when writing a function that creates a process, i have to think about the purpose of the function and understand if the caller is calling for the purpose of launching the process, or some other. it does look like i should (and probably can) change my uses of call() to run(). my default kit of imports does, already, include run().
I understand that you often want to open the files in text mode. What I don't understand is the connection with this expression all(isinstance(x,str)for x in cmd)) which is true when all the command's arguments have the str type.
a thought came to me that maybe there should be separate modules for processes being created to continue running after the method returns vs. processes that will be expected to finish and be waited for before the method returns. but that should only be for interfaces where the caller normally expects or intends for a process to be started or run. other cases should be more abstract such as a call to download a file where the caller does not need to know if it is being done by the module's code or by invoking curl.

i previously had that all() checking for (bytes,bytearray). but i was also using not because of which way the logic was for the universal_newlines= keyword argument. i thought the code looked simpler by changing (bytes,bytearray) to str and doing away with the not.