Resetar variável em Python

Pessoal, eu tenho esse código em Python:

#!/usr/bin/env python
from subprocess import Popen, PIPE
import sys, os

def plymouth_install(p):
	ply = os.path.abspath('Personalization/User_Plymouth')
	arch = os.listdir(ply)
	r = ''
	
	while (r != 's') or (r != 'n'):
		pm = f'{len(arch) + 1}'
		r = input('\nANTES DE COMEÇAR A PERSONALIZAÇÃO DO SISTEMA COM O NOVO TEMA DE BOOT, \nCOLOQUE O ARQUIVO COMPACTADO QUE DESEJA USAR COMO TEMA \nDENTRO DO DIRETÓRIO New_System/Personalization/Plymouth. \nIMPORTANTE: O NOME DAS PASTAS NÃO PODEM CONTER ESPAÇOS VAZIOS. \nDESEJA CONTINUAR O PROCEDIMENTO? (S/N) \n').lower( )
		if r == 'n':
			break
		if r == 's':
			if len(arch) == 0:
				print(f'\nNENHUM TEMA FOI ENCONTRADO. \nINSIRA O TEMA QUE DESEJA USAR COMO PLYMOUTH NO \nDIRETÓRIO {ply}\n') 
			if len(arch) == 1:
				fl = arch[0]
				apply_plymouth(p, fl)
			if len(arch) > 1:
				while int(pm) >= len(arch):
					print('\nDIGITE O NÚMERO CORRESPONDENTE AO TEMA QUE DESEJA USAR:\n')
					for x in range(len(arch)):
						print(f'{x + 1} - {arch[x]}')
					pm = input('> ')
					if int(pm) >= len(arch):
						print(f'ESCOLHA APENAS UM TEMA.')
				else:
					fl = arch[0]
					apply_plymouth(p, fl)
					
		print('PLYMOUTH CONFIGURADO COM SUCESSO. \nPRESSIONE A TECLA ENTER PARA SAIR.')
		ply = input('')
		del ply
		os.system('clear')
		break

def apply_plymouth(p, fl):
	pswd = p
	ply = os.path.abspath('Personalization/User_Plymouth')
	try:
		print('try')
		os.chdir(ply)
		cmd_01 = [[f'tar -xvf ACMM_Mac_Plymouth.tar.xz'], [f'sudo -S chmod +rwx {ply}/ACMM_Mac_Plymouth']]
		for x in cmd_01:
			p = Popen(x, stdin = PIPE, stderr = PIPE, universal_newlines = True, shell = True)
			p.stdin.write(pswd)
			p.stdin.flush( )
			stdout, stderr = p.communicate( )
			print(stdout, stderr)
		print('Descompactando')
		os.popen('clear')
		os.chdir(f'{ply}/ACMM_Mac_Plymouth')
		
		cmd_01 = [[f'sudo -S cp -rf apple-mac-plymouth /usr/share/plymouth/themes/ -v'], ['sudo -S update-alternatives --install /usr/share/plymouth/themes/default.plymouth default.plymouth /usr/share/plymouth/themes/apple-mac-plymouth/apple-mac-plymouth.plymouth 100'], ['sudo -S update-alternatives --set default.plymouth /usr/share/plymouth/themes/apple-mac-plymouth/apple-mac-plymouth.plymouth'], ['sudo -S update-initramfs -u']]
		for x in cmd_01:
			p = Popen(x, stdin = PIPE, stderr = PIPE, universal_newlines = True, shell = True)
			p.stdin.write(pswd)
			p.stdin.flush( )
			stdout, stderr = p.communicate( )
			print(stdout, stderr)
	except Exception as e:
		exc_type, exc_obj, exc_tb = sys.exc_info( )
		fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
		err = f"\n{e} \n{exc_type} \n{fname} \n{exc_tb.tb_lineno} \n"
		#print(err)

	os.chdir(ply)

	try:
		cmd_01 = [[f'sudo -S rm -rf ACMM_Mac_Plymouth']]
		for x in cmd_01:
			p = Popen(x, stdin = PIPE, stderr = PIPE, universal_newlines = True, shell = True)
			p.stdin.write(pswd)
			p.stdin.flush( )
			stdout, stderr = p.communicate( )
			#print(stdout, stderr)
	except Exception as e:
		exc_type, exc_obj, exc_tb = sys.exc_info( )
		fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
		err = f"\n{e} \n{exc_type} \n{fname} \n{exc_tb.tb_lineno} \n"
		#print(err)
		
	os.system('clear')

Ele esta funcional, pelo menos, nas distros que eu testei, Ele serve pra instalar um plymouth (tema da tela de boot) personalizado no Linux. Depois de ser executado, volta pro menu principal do programa. Ate aí, tudo certo. Esse e o esperado.
O problema é se alguém, por qualquer motivo que seja, quiser rodar esse mesmo programa novamente, aí ele dá um erro de diretório ou arquivo não encontrado.
A questão é que a variável ply é a responsável por pegar o caminho absoluto do arquivo e na primeira vez que ela atua a variável guarda a seguinte informação /caminho/ fora/da/pasta/do/programa/caminho/dentro/da/pasta/do/programa mas na segunda vez a variável fica assim /caminho/ fora/da/pasta/do/programa/caminho/dentro/da/pasta/do/programa/caminho/dentro/da/pasta/do/programa e vai piorando a cada vez que o programa é executado.
Eu tentei resolver isso atribuindo um input a variável e usando o del ply pra poder resetar a variável depois de cada vez que o programa roda em sequência, mas não funciona. Se eu executar uma outra funcionalidade do programa ou fechar e tornar a abrí-lo pra depois executar esse código acima, tudo funciona de boa. O problema é só se executar em sequência.
Eu sei que alguns podem se perguntar porque alguém executaria isso em sequência. Mas como a intenção e fazer com que esse programa, depois de finalizado, seja usado por qualquer pessoa, então ele pode ser usado por usuários e “usuários”.
Se alguém puder me ajudar, agradeço.

1 curtida

Considerando que a função é praticamente global (já que você chama ela em vários lugares), considere deixar ela global de fato:

from subprocess import Popen, PIPE
import sys, os


ply = os.path.abspath('Personalization/User_Plymouth')


def plymouth_install(p):
	arch = os.listdir(ply)
...

Assim você garante que a função é chamada apenas uma vez

1 curtida

O que acontece é que você pede para o processo obter o caminho completo do arquivo, relativo à pasta de trabalho atual, na primeira linha da função plymouth_install, mas na terceira linha da função apply_plymouth, você usa a função os.chdir, que muda a pasta de trabalho.

A pasta de trabalho é atrelada ao processo atual, e não tem como “deletar” ela. Porém, é possível restaurá-la ao valor original. Logo, depois que terminar as tarefas da função apply_plymouth, deve-se fazer um os.chdir("../..") para voltar duas pastas atrás (ou salvar os.path.abspath('.') em outra variável e dar o chdir nela).


PS: não é uma boa prática ficar chamando o shell a cada meio segundo em projetos com uma linguagem script já poderosa como Perl ou Python. Há funções na própria linguagem para o que você está procurando, e diferente de fichar chamando o shell, não há risco do comando ir pro ralo abaixo quando um espaço aparece.

Se for insistir em usar comandos externos, pelo menos faça a separação dos argumentos já no Python (o primeiro argumento do Popen sendo [ "tar", "xvf" , arquivo_usuario ] – note que é separado por espaços no shell são itens separados na lista – e definindo o valor de shell=False).

1 curtida

Realmente faz sentido.

Eu coloquei assim:

#!/usr/bin/env python
from subprocess import Popen, PIPE
import sys, os

def plymouth_install(p):
	ply = os.path.abspath('Personalization/User_Plymouth')
	arch = os.listdir(ply)
	r = ''
	
	print(ply)

e comentei o resto do código e a variável não mudou. Agora que eu ja sei onde esta o erro, fica mais fácil de consertar.

Mas tem uma parte na função apply_plymouth onde eu coloco o seguinte os.chdir('ply'). Isso náo seria o suficiente pra fazer a variável voltar a atribuição do início? Pois eu preciso voltar pra esse diretório pra deletar a pasta que foi descompactada antes e aí termina o programa. Estranho isso.

Não, isso mudaria para uma subpasta chamada ply dentro da pasta de trabalho atual (que já é o valor de os.path.abspath('Personalization/User_Plymouth').

1 curtida

Entendi. Nesse caso eu poderia usar o chdir logo após o programa executar tudo, não e isso? Ou teria uma outra posição melhor?
Agora vai dar pra eu consertar. Valeu.

Funcionou.