Summary
Working with directories in the shell is different from working with directories from within a program - transplanting commands will not work.
Even so, there are specific things in the use of directories with programs that the
Python only simplified after version 3.5 - in the full text I explain better.
But for your specific problem, you can do:
from pathlib import Path
desktop = Path.home() / "Desktop"
pastinha = desktop.mkdir("Pastinha")
and, from there on, for any file operation in that folder - for example,
create a "data.db" file inside:
arq = open(pastinha / "dados.db", "wt")
Note that no "chdir" or equivalent was used - explain below.
Create a Python directory
First: call supprocess.call("mkdir pastinha")
to create a folder is the same as calling a locksmith to open the door of your home when you are holding the key. Instead of putting the key in the door and turning, you wait until the key chain comes, picks up his tools, opens the door, and pays the fee for it.
That is why in this way mkdir is invoked as an external process of the operating system - the system has to create a new process in the table of processes, reserve the resources for the same, read from HD the file with the mkdir binary, and then terminate the process. All this usually happens very fast, but it uses a thousand to 10 thousand times more computational resources than simply calling the operating system to create a directory.
This can be done directly from Python using the module os
: os.mkdir("Pastinha")
.
From Python 3.5 however, there is a new API for everything that is related to the file system, which is pathlib - it has a unified object to represent filenames or directories, which already has methods to open or read a file directly, or create a new directory underneath that one. With pathlib, the full code would be:
from pathlib import Path
desktop = Path.home() / "Desktop"
desktop.mkdir("Pastinha")
(the use of getpass.getuser
to get the user’s name was suggested by Rafaeltuber in another reply, I would not remember doing that. But Anderson reminded (in the comments) that there is Path.home()
that does this more directly, not knowing the user’s name)
Changing directory
You nay directory change! :-)
Here’s what makes your code not work. The question of "being in a directory" is something relative - the "working directory" is a variable of each process (program) that is running. Before calling the program in Python, if we are in a terminal (like the cmd
), we change to the desired directory with cd pasta/pasta<enter>
. When the program is called, its working directory is the one it was called "folder/folder" from - if you use any relative file path (that is, without starting with a "/" or " that goes back to the root of the file-system, this is where the actions happen). And this happens because it has an internal variable of the operating system, associated with your program, which says that the "current working directory" (CWD) is this "folder/folder".
If your own program makes a call to the operating system saying "I am changing the current program’s workbook", it is updated. If your program calls os.chdir("../outra_pasta")
, the operating system understands that the "current working directory" (CWD) is now "folder/other_folder". Only when your show is over, and you’re back at the CMD, what’s the CWD of the CMD? Just the "folder/folder" - it did not move just because the child process, your Python script, changed the directory itself.
When you use a subprocess to call "chdir" the same thing happens. "chdir" is a command embedded in the shell. In the case of Windows the "cmd" itself. The operating system then creates a new process, runs a new CMD internally, as described above, this cmd calls the operating system to change own working directory for another - -and terminates. The execution of your Python program continues in the working directory it was in before.
However the story does not end there - even calling os.chdir(...)
, and by correctly changing the working directory of your program, this practice is not recommended in modern programs. That’s why, since the working directory is a state of the entire program, any function that changes it will change the directory also in the functions that called it, and any other place in the program - that is, it is not a "watertight" change. If the program is multi-threaded then the situation is even worse. In other words: in a more complex program that uses directory change, it does not give a part of the program to know which is the current directory - another function may have changed the directory.
The good practice then is that any and all actions in the file system use the absolute path - starting from the "/" directory, or, in the case of Windows, from the drive name: "C:/". Prior to pathlib this implied that programs that were guaranteed to work had to stay using os.path.join
all the time - with Pathlib it becomes much simpler.
How to proceed to perform actions in a specific directory
In modern Python then, instead of trying to change the directory, the most correct
It is simpler to store the directory where you want to do the operations in a variable, and for any operation - be it create a file, another directory, etc... use the operator /
(the same used for division of numbers - it is re-signified for Pathlib objects) to create new objects Path
:
desktop = pathlib.Path("/users/xxxx/Desktop")
minha_pasta = desktop.mkdir("Minha Pasta")
# Criar novo arquivo para scrita dentro dessa nova pasta:
with (minha_pasta / "meu_arquivo.txt").open("wt") as arq:
# dentro deste bloco, "arq" é o arquivo
# DEsktop/Minha Pasta/meu_arquivo.txt" aberto para escrita
....
About getting to the user’s Desktop, it could not be
Path.home() / 'Desktop'
, which it uses as a basisos.path.expanduser()
?– Woss
Ah - can also - better than using the
getpass
, which in that case does not even need to be imported– jsbueno