0

When I am running following code with a on a system not existing /AnewDir directory then after the code exits there is a new directory on the system:

from subprocess import Popen, PIPE
from os.path import isdir
from time import sleep
from os import system

#v--- (Miracle-SWITCH) NEW LINE / BACKSPACE  
#""" Move cursor after the beginning  #  but before the triple quotes.  
#^-- Press Return to switch to execution of the code part removing the 
# directory. Then press Backspace to switch back to execution of the 
# leading code block (miracle-SWITCH). 
sudoShCmd = Popen(["sudo", "-S", "mkdir", "/AnewDir"], stdin=PIPE) 
sudoShCmd.stdin.write(b'PUT YOUR ROOT PASSWORD HERE') # <<< ###

sleep(1); print()

system("if [ -x /AnewDir ]; then echo isThere; else echo isNotThere; fi")
print(f'{isdir("/AnewDir")=}')

sleep(3); print()

system("if [ -x /AnewDir ]; then echo isThere; else echo isNotThere; fi")
print(f'{isdir("/AnewDir")=}')

"""
sudoShCmd = Popen(["sudo", "-S", "rmdir", "/AnewDir"], stdin=PIPE) 
sudoShCmd.stdin.write(b'PUT YOUR ROOT PASSWORD HERE') # <<< ###
#sleep(1); print()
system("if [ -x /AnewDir ]; then echo isThere; else echo isNotThere; fi")
print(f'{isdir("/AnewDir")=}')
#"""

but the checks for the existence of the directory fail to provide the proper status reporting that the directory isn't there (but you can check from the console of with a File Manager that the directory is there). It doesn't help to pause for 3 seconds in order to get the proper response to the question if the directory exist.

Is there a way to reliably check from within the code creating the directory if the directory was actually created?

Or is the above question only the result of total confusion? Am I missing something in my way of thinking what is happening there?

The answer provided by Constantin Hong shows a way to change the code preceding the checks for the directory existence so that the checks deliver the proper result. This shows that the preliminary code somehow causes the problem, but ... to make these checks work properly isn't necessary to change the code. It would be sufficient to run them from another script after the exit of the script creating/deleting the directory ...

Does the provided answer imply that there is no way to reliably check for existence of a directory in the same code which creates it?

Claudio
  • 7,474
  • 3
  • 18
  • 48

2 Answers2

1

Your code is good except for these.

sudoShCmd = Popen(["sudo", "-S", "mkdir", "/AnewDir"], stdin=PIPE) 
sudoShCmd.stdin.write(b'PUT YOUR ROOT PASSWORD HERE') # <<< ###

Is there a way to reliably check from within the code creating the directory if the directory was actually created?

Yes. isdir() function is a reliable way to check the existence of the directory.

This is my suggestion.

Interactive mode @Aniket Inge's idea

password = input("PUT YOUR ROOT PASSWORD HERE")
sudoShCmd = system('echo {password} | sudo -S mkdir /AnewDir 2>/dev/null'.format(password=password))

Non-interactive mode

password = 'yourpassword'
sudoShCmd = system('echo {password} | sudo -S mkdir /AnewDir 2>/dev/null'.format(password=password))

Non-interactive mode with Popen

from subprocess import Popen, PIPE, DEVNULL
password = Popen(["echo", "YOURPASSWORD"], stdout=PIPE) 
sudoShCmd = Popen(["sudo", "-S", "mkdir", "/AnewDir"], stdin=password.stdout, stderr=DEVNULL) 
sudoShCmd.communicate()

The result


isThere
isdir("/AnewDir")=True

isThere
isdir("/AnewDir")=True

The interactive mode code

from subprocess import Popen, PIPE
from os.path import isdir
from time import sleep
from os import system

password = input("PUT YOUR ROOT PASSWORD HERE")
sudoShCmd = system('echo {password} | sudo -S mkdir /AnewDir 2>/dev/null'.format(password=password)) 
sleep(1); print()

system("if [ -x /AnewDir ]; then echo isThere; else echo isNotThere; fi")
print(f'{isdir("/AnewDir")=}')

sleep(3); print()

system("if [ -x /AnewDir ]; then echo isThere; else echo isNotThere; fi")
print(f'{isdir("/AnewDir")=}')
Constantin Hong
  • 701
  • 1
  • 2
  • 16
  • See my updated answer for report on your proposal for change in my code. Sorry ... have no idea how it comes that you get an output from the code you provide in your answer. – Claudio Mar 09 '23 at 18:41
  • @Claudio I'm sorry I made a mistake. I changed my answer. Also, the method I suggested has a [security concern](https://stackoverflow.com/a/24257940/20307768) – Constantin Hong Mar 09 '23 at 20:07
  • Why are you using `os.system()` and not `subprocess.run()`? The mainstream opinion is to avoid usage of `os.system()` isn't it? OK ... you found a way to change the preliminary code in order to make the checks delivering the right result ... BUT ... without adapting the code to the needs of the checks does not make them a better check, right? WHAT prevents the checks to give the right response in case of the code I am using? The actual question seem to be not how to make the checks work ... but which checks to use in order to give the proper answer in case of the code in the question. – Claudio Mar 09 '23 at 22:13
  • In other words, your answer answers the question "How can I change the code so that the checks work as expected?". That `isdir()` does not reliably report the actual status of a directory at the time it runs in code seem to be shown by the code in question - right or not? Are there other methods of checking which won't fail and don't need a change in the preliminary code?. – Claudio Mar 09 '23 at 22:24
  • @Claudio I read the practice just now. In my opinion, I'm familiar with shell scripting(Bash, Zsh). Therefore I can use it. Also except that, I don't know the way to pipe a password to `sudo -S mkdir /AnewDir` without os.system() which means I couldn't find the way how to use `|` in Popen. I want to know it. – Constantin Hong Mar 09 '23 at 23:25
  • Regarding the other questions, I will think about them this weekend. – Constantin Hong Mar 09 '23 at 23:36
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/252429/discussion-between-constantin-hong-and-claudio). – Constantin Hong Mar 09 '23 at 23:38
0

Your opinion that the check of existence of the created directory delivers a wrong result is based on an erroneous assumption that at the time of the check the directory already exists, but it doesn't. The check delivers the right result. At the time of the check the directory is not yet created.

You can check it out yourself increasing the time of the gap between the commands to see that the directory is not created within the looong time of waiting. It will be created at the very end when the script is in the process of exiting flushing data streams what then causes the spawn Popen() to become active and create the directory AFTER the code lines checking for the directory existence are executed.

You think in terms of sequential execution of lines of code, but with the Popen() method you spawn another line of code execution which acts more or less on its own, so it is possible that the order in which from now on the lines are executed can get reversed and results in what you have observed.

Check out the answers and comments to the question: Why does the Python code creating a directory get executed AFTER the code at the end of the script? for more details.

Below code where the checks show the proper directory status because the creation of the directory does not run parallel to the main execution path of the script:

from subprocess import run
from os.path import isdir
run('echo YOUR_ROOT_PASSWORD | sudo -S mkdir /AnewDir 2>/dev/null', shell=True) 
print(f'{isdir("/AnewDir")=}')

The "trick" is to use the option "shell=True" coupled with providing the password via a PIPE directly in the command line.

Claudio
  • 7,474
  • 3
  • 18
  • 48