Artigos

Módulo OS - Interagindo com o Sistema Operacional

Introdução

O módulo OS fornece diversas funções para interagirmos com o Sistema Operacional. Este módulo abstrai as funcionalidades do Sistema Operacional e fornece métodos Python para navegar, criar, excluir e modificar arquivos e diretórios, assim como execução de comandos e manipulação de caminhos.

Funcionalidades Básicas

Iniciaremos explorando o módulo com exemplos. Primeiramente é essencial que façamos o import do módulo OS. Lembrando que ele já vem embutido no Python, então não há necessidade de instalarmos ele.

import os

Podemos utilizar a função dir() para obtermos a lista de métodos e atributos disponíveis para trabalharmos

print(dir(os))

Iremos obter o seguinte output:

['CLD_CONTINUED', 'CLD_DUMPED', 'CLD_EXITED', 'CLD_TRAPPED', 'DirEntry', 'EX_CANTCREAT', 'EX_CONFIG', 'EX_DATAERR', 'EX_IOERR', 'EX_NOHOST', 'EX_NOINPUT', 'EX_NOPERM', 'EX_NOUSER', 'EX_OK', 'EX_OSERR', 'EX_OSFILE', 'EX_PROTOCOL', 'EX_SOFTWARE', 'EX_TEMPFAIL', 'EX_UNAVAILABLE', 'EX_USAGE', 'F_LOCK', 'F_OK', 'F_TEST', 'F_TLOCK', 'F_ULOCK', 'MutableMapping', 'NGROUPS_MAX', 'O_ACCMODE', 'O_APPEND', 'O_ASYNC', 'O_CLOEXEC', 'O_CREAT', 'O_DIRECT', 'O_DIRECTORY', 'O_DSYNC', 'O_EXCL', 'O_LARGEFILE', 'O_NDELAY', 'O_NOATIME', 'O_NOCTTY', 'O_NOFOLLOW', 'O_NONBLOCK', 'O_RDONLY', 'O_RDWR', 'O_RSYNC', 'O_SYNC', 'O_TRUNC', 'O_WRONLY', 'POSIX_FADV_DONTNEED', 'POSIX_FADV_NOREUSE', 'POSIX_FADV_NORMAL', 'POSIX_FADV_RANDOM', 'POSIX_FADV_SEQUENTIAL', 'POSIX_FADV_WILLNEED', 'PRIO_PGRP', 'PRIO_PROCESS', 'PRIO_USER', 'P_ALL', 'P_NOWAIT', 'P_NOWAITO', 'P_PGID', 'P_PID', 'P_WAIT', 'PathLike', 'RTLD_DEEPBIND', 'RTLD_GLOBAL', 'RTLD_LAZY', 'RTLD_LOCAL', 'RTLD_NODELETE', 'RTLD_NOLOAD', 'RTLD_NOW', 'R_OK', 'SCHED_BATCH', 'SCHED_FIFO', 'SCHED_IDLE', 'SCHED_OTHER', 'SCHED_RESET_ON_FORK', 'SCHED_RR', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'ST_APPEND', 'ST_MANDLOCK', 'ST_NOATIME', 'ST_NODEV', 'ST_NODIRATIME', 'ST_NOEXEC', 'ST_NOSUID', 'ST_RDONLY', 'ST_RELATIME', 'ST_SYNCHRONOUS', 'ST_WRITE', 'TMP_MAX', 'WCONTINUED', 'WCOREDUMP', 'WEXITED', 'WEXITSTATUS', 'WIFCONTINUED', 'WIFEXITED', 'WIFSIGNALED', 'WIFSTOPPED', 'WNOHANG', 'WNOWAIT', 'WSTOPPED', 'WSTOPSIG', 'WTERMSIG', 'WUNTRACED', 'W_OK', 'XATTR_CREATE', 'XATTR_REPLACE', 'XATTR_SIZE_MAX', 'X_OK', '_Environ', '__all__', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', '_check_methods', '_execvpe', '_exists', '_exit', '_fspath', '_fwalk', '_get_exports_list', '_putenv', '_spawnvef', '_unsetenv', '_wrap_close', 'abc', 'abort', 'access', 'altsep', 'chdir', 'chmod', 'chown', 'chroot', 'close', 'closerange', 'confstr', 'confstr_names', 'cpu_count', 'ctermid', 'curdir', 'defpath', 'device_encoding', 'devnull', 'dup', 'dup2', 'environ', 'environb', 'error', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fchdir', 'fchmod', 'fchown', 'fdatasync', 'fdopen', 'fork', 'forkpty', 'fpathconf', 'fsdecode', 'fsencode', 'fspath', 'fstat', 'fstatvfs', 'fsync', 'ftruncate', 'fwalk', 'get_blocking', 'get_exec_path', 'get_inheritable', 'get_terminal_size', 'getcwd', 'getcwdb', 'getegid', 'getenv', 'getenvb', 'geteuid', 'getgid', 'getgrouplist', 'getgroups', 'getloadavg', 'getlogin', 'getpgid', 'getpgrp', 'getpid', 'getppid', 'getpriority', 'getresgid', 'getresuid', 'getsid', 'getuid', 'getxattr', 'initgroups', 'isatty', 'kill', 'killpg', 'lchown', 'linesep', 'link', 'listdir', 'listxattr', 'lockf', 'lseek', 'lstat', 'major', 'makedev', 'makedirs', 'minor', 'mkdir', 'mkfifo', 'mknod', 'name', 'nice', 'open', 'openpty', 'pardir', 'path', 'pathconf', 'pathconf_names', 'pathsep', 'pipe', 'pipe2', 'popen', 'posix_fadvise', 'posix_fallocate', 'pread', 'preadv', 'putenv', 'pwrite', 'pwritev', 'read', 'readlink', 'readv', 'register_at_fork', 'remove', 'removedirs', 'removexattr', 'rename', 'renames', 'replace', 'rmdir', 'scandir', 'sched_get_priority_max', 'sched_get_priority_min', 'sched_getaffinity', 'sched_getparam', 'sched_getscheduler', 'sched_param', 'sched_rr_get_interval', 'sched_setaffinity', 'sched_setparam', 'sched_setscheduler', 'sched_yield', 'sendfile', 'sep', 'set_blocking', 'set_inheritable', 'setegid', 'seteuid', 'setgid', 'setgroups', 'setpgid', 'setpgrp', 'setpriority', 'setregid', 'setresgid', 'setresuid', 'setreuid', 'setsid', 'setuid', 'setxattr', 'spawnl', 'spawnle', 'spawnlp', 'spawnlpe', 'spawnv', 'spawnve', 'spawnvp', 'spawnvpe', 'st', 'stat', 'stat_result', 'statvfs', 'statvfs_result', 'strerror', 'supports_bytes_environ', 'supports_dir_fd', 'supports_effective_ids', 'supports_fd', 'supports_follow_symlinks', 'symlink', 'sync', 'sys', 'sysconf', 'sysconf_names', 'system', 'tcgetpgrp', 'tcsetpgrp', 'terminal_size', 'times', 'times_result', 'truncate', 'ttyname', 'umask', 'uname', 'uname_result', 'unlink', 'unsetenv', 'urandom', 'utime', 'wait', 'wait3', 'wait4', 'waitid', 'waitid_result', 'waitpid', 'walk', 'write', 'writev']

Como podemos observar, existe um grande número de métodos e atributos, neste guia veremos os mais utilizados e importantes.

  1. os.name Fornece o nome do módulo dependente do sistema operacional importado.
print(os.name)

Como estou utilizando um sistema Linux, será retornado para mim: 'posix', dependendo do seu Sistema Operacional, você terá um resultado diferente.

  1. os.getcwd() Função que retorna o Current Working Directory, que seria o diretório que estamos trabalhando atualmente, nesse caso, o diretório no qual o arquivo Python está sendo executado.
print(os.getcwd())

O código retornará '/home/akira/Documentos/Python/Modulo-OS', isso significa que o script Python reside no diretório Modulo-OS ou o interpretador foi executado dentro dele.

  1. os.chdir() Método que nos permite alterar o nosso Current Working Directory, recebe um caminho como parâmetro.
os.chdir('/home/akira/Documentos/Python/')

Agora se utilizarmos o comando os.getcwd(), será retornado: '/home/akira/Documentos/Python'

Irei agora retornar ao diretório Modulo-OS

os.chdir('/home/akira/Documentos/Python/Modulo-OS')
  1. os.listdir() Retorna uma lista contendo os nomes das entradas no diretório fornecido pelo caminho. A lista está em ordem arbitrária e não inclui as entradas especiais ’.’ e ’..’ mesmo se eles estiverem presentes no diretório.
os.listdir()

Será retornada a seguinte lista como output:

['texto.txt',
 'Imagens',
 'index.html',
 'Modulo-OS.ipynb',
 'Artigos',
 '.ipynb_checkpoints']

Como podemos ver, nos foi apresentado todos os arquivos e diretórios que estão presentes no diretório Modulo-OS.

  1. os.mkdir() Método que nos permite criar um diretório, se eventualmente ele já existir, nos será retornado um erro FileExistsError, vejamos um exemplo.
os.mkdir('Python-Scripts')

Será criado um diretório chamado Python-Scripts dentro do nosso Current Working Directory.

  1. os.makedirs() Similar ao método anterior, porém é capaz de criar diversos diretórios aninhados.
os.makedirs('Projeto/template')

Será criado um diretório de nome Projeto e dentro dele mais um diretório de nome template.

  1. os.rename() Método que nos permite renomear um arquivo ou diretório.
os.rename('texto.txt', 'textos.txt')

Neste caso estamos alterando o arquivo texto.txt(origem) para textos.txt(destino). Também é possível alterarmos o nome de diretórios

os.rename('Imagens', 'Imgs')

O diretório Imagens agora se chamará Imgs.

  1. os.stat() Nos fornece informações sobre um arquivo, podemos obter por exemplo o tamanho de um arquivo em bytes ao acessar o atributo st_size
os.stat('textos.txt').st_size

Será retornado 3389, pois trata-se de um pequeno arquivo de texto, também é possível obtermos a última vez que o arquivo foi modificado ao acessarmos o atributo st_mtime, porém ele nos retornará apenas um timestamp, então iremos utilizando o módulo padrão do Python datetime para convertermos em um formato legível para humanos.

from datetime import datetime

data_mod = os.stat('textos.txt').st_mtime
print(datetime.fromtimestamp(data_mod))

Será retornado o seguinte output: 2020-04-28 04:08:48.910715

  1. os.walk() Nos permite percorrer todos os diretórios subjacentes ao nosso Current Working Directory, nos dando acesso ao caminho, diretórios e arquivos.
for dirpath, dirnames, filenames in os.walk('/home/akira/Documentos/Python/Modulo-OS'):
    print(f'Caminho Atual: {dirpath}')
    print(f'Diretórios: {dirnames}')
    print(f'Arquivos: {filenames}')

Output:

Caminho Atual: /home/akira/Documentos/Python/Modulo-OS
Diretórios: ['Imgs', 'Artigos', '.ipynb_checkpoints']
Arquivos: ['textos.txt', 'index.html', 'Modulo-OS.ipynb']
Caminho Atual: /home/akira/Documentos/Python/Modulo-OS/Imgs
Diretórios: []
Arquivos: []
Caminho Atual: /home/akira/Documentos/Python/Modulo-OS/Artigos
Diretórios: []
Arquivos: []
Caminho Atual: /home/akira/Documentos/Python/Modulo-OS/.ipynb_checkpoints
Diretórios: []
Arquivos: ['Modulo-OS-checkpoint.ipynb']
  1. os.environ.get() Nos permite obter o valor de uma determinada variável de ambiente de nosso Sistema Operacional.
os.environ.get('HOME')

Em meu caso específico, será retornado '/home/akira'.

  1. os.mknod() É um método que nos possibilita criar um arquivo em um caminho especificado. Iniciaremos criando dois caminhos para trabalharmos.

Utilizando f-string

path = f'{os.environ.get("HOME")}/arquivo.txt' 

Utilizando o método os.path.join(), que retorna uma string representando o caminho para o qual o link simbólico aponta. O resultado pode ser um nome de caminho absoluto ou relativo.

file_path = os.path.join(os.environ.get("HOME"), 'file.txt')

Agora que construímos dois caminhos, podemos utilizá-los para construir os arquivos desejados.

os.mknod(path)
os.mknod(file_path)

Observe que ambos serão criados em /home/akira.

  1. os.path O submódulo path nos permite trabalharmos exclusivamente com caminhos, diretórios e arquivos, vejamos alguns de seus métodos importantes.

Obter o Nome do Arquivo em um Determinado Caminho com o método basename().

os.path.basename(file_path)

Será retornado 'file.txt'.

Obter Somente os Diretórios em um Determinado Caminho com o método dirname().

os.path.dirname(path)

O output será '/home/akira'.

Dividindo os Diretórios e o Arquivo através do método split().

os.path.split(file_path)

Teremos como retorno uma tupla: ('/home/akira', 'file.txt').

Podemos também checar pela existência de um caminho com o método exists().

os.path.exists('/home/akira')

Será retornado True, uma vez que este caminho existe em meu sistema.

O método isdir() nos permite checar se um determinado caminho é um diretório.

os.path.isdir('/home/akira/Documentos/Python/Modulo-OS')

É retornado o valor True, uma vez que Modulo-OS é um diretório.

O método isfile() nos permite checar se um determinado caminho é um arquivo.

os.path.isfile('/home/akira/Documentos/Python/Modulo-OS/index.html')

É retornado o valor True, uma vez que index.html é um arquivo.

O método splitext() nos permite separar a raiz do caminho e a extensão do arquivo, vejamos um exemplo.

os.path.splitext('/home/akira/Documentos/Python/Modulo-OS/index.html')

Ele irá nos retornar uma tupla com duas entradas: ('/home/akira/Documentos/Python/Modulo-OS/index', '.html'), na primeira entrada temos acesso o caminho absoluto do arquivo sem sua extensão e na segunda entrada temos acesso apenas a extensão do arquivo.

  1. Com o auxílio do módulo glob podemos buscar por padrões de forma a encontrarmos arquivos com mais facilidade. É importante lembrarmos que este módulo já vem embutido no Python, vejamos então um exemplo de como podemos utilizá-lo.
import glob
glob.glob('*.txt')

O * trata-se de um wildcard que irá buscar todos os arquivos que terminam com .txt, independente do seu nome.

Em meu caso, será retornado ['textos.txt'], pois existe apenas um arquivo .txt no diretório que estou trabalhando.

  1. Com o auxílio do módulo shutil, também embutido por padrão no Python, podemos realizar operações de alto nível em arquivos ou coleções de arquivos, por exemplo:

Através do método copyfile() podemos copiar um arquivo:

import shutil
shutil.copyfile('textos.txt','texto.txt')

Será criada uma cópia do arquivo textos.txt com o nome de texto.txt.

Através do método move() somos capazes de mover um arquivo para um diretório de nossa escolha:

shutil.move('textos.txt', 'Artigos')

Nesse caso específico, estamos movendo o arquivo textos.txt para o diretório Artigos.

  1. Para finalizarmos o tutorial, veremos o método os.system(), que nos permite executar um comando em uma subshell. É implementado ao invocar a função padrão do C chamada de system() e possui as mesmas limitações dela.

Executando o comando date

os.system('date')

Nos trará a data e tempo atual de nosso sistema: ter abr 28 23:25:16 -03 2020.

Executando o comando lscpu

os.system('lscpu')

Nos trará detalhes sobre o CPU de nossa máquina:

Arquitetura:                x86_64
Modo(s) operacional da CPU: 32-bit, 64-bit
Ordem dos bytes:            Little Endian
CPU(s):                     4
...

Conclusão

Através desse tutorial fomos capazes de explorar as funcionalidades mais utilizadas do Módulo OS, nos fornecendo habilidades como a de manipular arquivos, caminhos e até mesmo a execução de comandos e obtenção de informações, também vimos brevemente as funcionalidades das bibliotecas glob e shutil, capazes de nos oferecerem operações adicionais muito úteis.

Para mais detalhes técnicos é importante checarmos a documentação oficial de cada módulo.

Referências