|
31
|
Seguridad Informática / Seguridad / ¿Porque el comando shred hace tantas iteraciones (minimo 3) para un borrado seguro? | Seguridad
|
en: 13 Diciembre 2021, 23:23 pm
|
Buenos dias. Siempre he tenido una pregunta curiosa sobre el comando shred.... Como bien sabemos el comando shred, nos permite hacer un borrado seguro desde cualquier distribucion. Yo acostumbro mucho a utilizar estos parametros shred -vuz -n 10 <file>
Los parametros son: - -u: Elimina el archivo una vez sobrescrito
- -z: Sobrescribe el archivo a zeros (supongo que es el que se encarga de convertir los bits 1 a 0)
- -v: Pinta por pantalla el proceso de shred
- -n: Numero de sobrescrituras que hace antes de eliminar el archivo (si esta el -u)
Ok, hasta aquí lo entiendo, pero la pregunta del millon..... ¿Porque tantas pasadas? Yo lo entiendo así, y es que, el -z convierte los bits 1 a 0, haciendo que este no se pueda recuperar con alguna herramienta foranea (ejemplo: foremost). Se dice que (o lo he leido/oido) que cuando más pasadas más seguro es y...¿menos posible de recuperar? eso me suena, pero de donde. En caso de que se pueda recuperar,¿no es imposible auque sea una unica pasada (sobrescrito una iteracion)? No acabo de entender porque tantas iteraciones... Es por mera curiosidad...para entender más sobre su funcionamiento auque no he visto ningún sitio que explicara la razon de las iteraciones.... Además la salida que este imprime en pantalla....como lo interpreto?? $ shred -uzv -n 5 2021-12-04-23-07-11.031-VBoxSVC-1990.log shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: pass 1/6 (random)... shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: pass 2/6 (000000)... shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: pass 3/6 (random)... shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: pass 4/6 (ffffff)... shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: pass 5/6 (random)... shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: pass 6/6 (000000)... shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: removing shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: renamed to 0000000000000000000000000000000000000000 shred: 0000000000000000000000000000000000000000: renamed to 000000000000000000000000000000000000000 shred: 000000000000000000000000000000000000000: renamed to 00000000000000000000000000000000000000 shred: 00000000000000000000000000000000000000: renamed to 0000000000000000000000000000000000000 shred: 0000000000000000000000000000000000000: renamed to 000000000000000000000000000000000000 shred: 000000000000000000000000000000000000: renamed to 00000000000000000000000000000000000 shred: 00000000000000000000000000000000000: renamed to 0000000000000000000000000000000000 shred: 0000000000000000000000000000000000: renamed to 000000000000000000000000000000000 shred: 000000000000000000000000000000000: renamed to 00000000000000000000000000000000 shred: 00000000000000000000000000000000: renamed to 0000000000000000000000000000000 shred: 0000000000000000000000000000000: renamed to 000000000000000000000000000000 shred: 000000000000000000000000000000: renamed to 00000000000000000000000000000 shred: 00000000000000000000000000000: renamed to 0000000000000000000000000000 shred: 0000000000000000000000000000: renamed to 000000000000000000000000000 shred: 000000000000000000000000000: renamed to 00000000000000000000000000 shred: 00000000000000000000000000: renamed to 0000000000000000000000000 shred: 0000000000000000000000000: renamed to 000000000000000000000000 shred: 000000000000000000000000: renamed to 00000000000000000000000 shred: 00000000000000000000000: renamed to 0000000000000000000000 shred: 0000000000000000000000: renamed to 000000000000000000000 shred: 000000000000000000000: renamed to 00000000000000000000 shred: 00000000000000000000: renamed to 0000000000000000000 shred: 0000000000000000000: renamed to 000000000000000000 shred: 000000000000000000: renamed to 00000000000000000 shred: 00000000000000000: renamed to 0000000000000000 shred: 0000000000000000: renamed to 000000000000000 shred: 000000000000000: renamed to 00000000000000 shred: 00000000000000: renamed to 0000000000000 shred: 0000000000000: renamed to 000000000000 shred: 000000000000: renamed to 00000000000 shred: 00000000000: renamed to 0000000000 shred: 0000000000: renamed to 000000000 shred: 000000000: renamed to 00000000 shred: 00000000: renamed to 0000000 shred: 0000000: renamed to 000000 shred: 000000: renamed to 00000 shred: 00000: renamed to 0000 shred: 0000: renamed to 000 shred: 000: renamed to 00 shred: 00: renamed to 0 shred: 2021-12-04-23-07-11.031-VBoxSVC-1990.log: removed
Si alguíen me lo puede explicar, para entender....se lo agradeceria. Gracias de antemano.
|
|
|
33
|
Programación / Scripting / Re: ¿Como coger el PID de un proceso hijo que ha hecho Event.set()? | Python3 multiprocessing Event
|
en: 6 Diciembre 2021, 12:23 pm
|
En realidad, mi pregunta era.... Como matar un proceso zombie cuando el proceso cliente se cierra. Para solucionar esto lo que hice es.... cuando esta escuchando clientes, además de iniciar un proceso hijo que será el cliente que se quiere conectar, creo un hilo en el proceso padre que estará en escucha de un evento que lo paso como parametro al proceso hijo del cliente. Y este que se activa al querrer cerrar el cliente, gracias al hilo obtendrá el evento activado y se encargará de unir el proceso hijo del cliente al proceso padre. Después hace un break para acabar el hilo Y finalmente se cierra el cliente. Pasos que he hecho: Primero, cuando escucho a los clientes, añado: while sockSSL: connection, address = sockSSL.accept() eventChildStop = multiprocessing.Event() subprocess = multiprocessing.Process(target=ClientListener, name="client", args=(connection, address,eventChildStop)) # This thread is responsible of close the client's child process threading.Thread(target=ClientListener.exitSubprocess,name="closeChildProcess",args=(eventChildStop,subprocess,)).start() subprocess.start() time.sleep(1)
Después in the nuevo metodo de la clase ClientsListener, cambio: @staticmethod def handlerEvent(event,childProcesses): while True: if event.is_set(): print(childProcesses) # terminate child process break time.sleep(.5)
por # This method get as argument the process child. For join it at parent process @staticmethod def exitSubprocess(event,process): while True: if event.is_set(): process.join() break time.sleep(.5)
cambio el nombre del metodo. No es que, añada otro, sino que cambio el nombre. en el proceso hijo al cerrar le añado un time.sleep de un 1 segundo para que le de tiempo al hijo a unir el proceso hijo al proceso padre. En el ultimo finally. class ClientListener: def __init__(self,conn,addr,event): try: self.conn, self.addr = conn, addr self.nick = "" self.__listenData() except (KeyboardInterrupt,SystemExit) as err: print(logFile().message(f"The host {self.nick} ({self.addr[0]}:{self.addr[1]}) left", True, "INFO")) except BaseException as err: type, object, traceback = sys.exc_info() file = traceback.tb_frame.f_code.co_filename line = traceback.tb_lineno print(logFile().message(f"{err} in {file}:{line}", True, "ERROR")) finally: try: ListClients().remove(self.conn) self.conn.close() except: None finally: Client(self.conn,self.addr).registre(self.nick,"DISCONNECTED",False) event.set() # This will delay 1 second to close the proccess, for this gives time at exitSubprocess method to join the client's child process with the parent process time.sleep(1)
Muchas gracias por vuestra atención y tiempo
|
|
|
34
|
Programación / Bases de Datos / Re: ayuda relacionar tablas
|
en: 14 Noviembre 2021, 15:25 pm
|
Aquí el campo dinero de la primera tabla sobra. el campo edad debe ser un FK a la PK de la segunda tabla ----------------------------------------- | PRIMERA TABLA | ----------------------------------------- | #* id INT(11) | | * nombre VARCHAR(20) | | F* edad INT(3) | |________________________| \ | / (M) | | (N) ----------------------------------------- | SEGUNDA TABLA | ----------------------------------------- | #* id INT(11) | | * edad INT(3) | | * dinero INT(20) | ------------------------------------------ Eso se hace con SQL. Creo que y lo más seguro es que PHPMyAdmin te permita hacer relaciones M:N por interfaz. El codigo sería CREATE TABLE PRIMERA_TABLA ( id INT(11) NOT NULL AUTO_INCREMENT, nombre VARCHAR(20) NOT NULL, edad INT(3) NOT NULL, CONSTRAINT PRIMERA_TABLA_PK PRIMARY KEY (id) ); CREATE TABLE SEGUNDA_TABLA ( id INT(11) NOT NULL AUTO_INCREMENT, edad INT(3) NOT NULL, dinero INT(20) NOT NULL, CONSTRAINT SEGUNDA_TABLA_PK PRIMARY KEY (id) ); ALTER TABLE PRIMERA_TABLA ADD CONSTRAINT PRIMERA_TABLA_PK FOREIGN KEY (edad) REFERENCES SEGUNDA_TABLA(id);
|
|
|
35
|
Programación / Scripting / ¿Como coger el PID de un proceso hijo que ha hecho Event.set()? | Python3 multiprocessing Event
|
en: 13 Noviembre 2021, 20:47 pm
|
Buenas. Estoy haciendo una arquitectura servidor-multicliente con sockets in python3 Para esto utilizo la libreria multiprocessing sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.bind(("",PORT)) sock.listen(CLIENTS) print(logFile().message(f"running ClassAdmin server, listen {CLIENTS} clients by port {PORT}...",True,"INFO")) sockSSL = context.wrap_socket(sock,server_side=True) childProcess = [] # This storages the childs processes event = multiprocessing.Event() # listening events of childs processes threading.Thread(target=Client.handlerEvent,name="exitChildProcess",args=(event,childProcess,)).start() while sockSSL: connection, address = sockSSL.accept() subproccess = multiprocessing.Process(target=Client,name="client",args=(connection,address,event)) subproccess.start() childProcess.append(subproccess) time.sleep(1)
En este código, la variable 'event' is un evento de la libreria multiprocessing que esta en escucha de que algún proceso hijo lo active. threading.Thread(target=Client.handlerEvent,name="exitChildProcess",args=(event,childProcess,)).start()
Ejecuto un hilo que ejecutará el metodo estatico handlerEvent de la clase Client que se encargará de ver si la variable 'event' es activado @staticmethod def handlerEvent(event,childProcesses): while True: if event.is_set(): print(childProcesses) # terminate child process break time.sleep(.5)
En el while ejecuto un subproceso, haciendo que para cada cliente que se conecte este se ejecutará en un proceso hijo. La clase Client es la siguiente: class Client: def __init__(self,conn,addr,event): try: self.conn, self.addr = conn, addr print(logFile().message(f"Client {self.addr[0]} connected by port {self.addr[1]}", True, "INFO")) self.__listenData() except (KeyboardInterrupt,SystemExit) as err: print(logFile().message(f"The client {self.addr[0]} left", True, "INFO")) except BaseException as err: type, object, traceback = sys.exc_info() file = traceback.tb_frame.f_code.co_filename line = traceback.tb_lineno print(logFile().message(f"{err} in {file}:{line}", True, "ERROR")) finally: try: self.conn.close() except: None finally: event.set() #[...] @staticmethod def handlerEvent(event,childProcesses): while True: if event.is_set(): print(childProcesses) # terminate child process break time.sleep(.5)
La idea es la siguiente: El cliente se conecta y este se ejecuta la clase Client en un proceso hijo. Y así para cada cliente que se conecte. En el segundo cliente se ejecuta la clase Client en otro proceso hijo y así consecutivamente.... Vale, pues. El init de la clase tengo try...except para si el cliente se cierra este ejecuta el exception (alguno de los dos). Pero siempre cuando se cierra un cliente se ejecutará el finally (el primero). Que se encargará de hacer: self.conn.close()
Y después se ejecutará el finally: event.set()
Por la cual el metodo handlerEvent de la clase Client detectará que el event es true @staticmethod def handlerEvent(event,childProcesses): while True: if event.is_set(): print(childProcesses) # terminate child process break time.sleep(.5)
y ejecutará lo que hay dentro del if. Mi idea es coger el PID del proceso hijo que ha hecho el event.set(). Pues así puedo hacer un for y matar el proceso que coincida con el PID. Pero como lo hago? En el cliente cuando hago el: event.set()
puedo obtener el PID del proceso hijo haciendo: finally: print(os.getpid()) event.set()
Sí hago esto si me obtiene el PID del hijo, pues este PID tendría que enviarlo al handlerEvent() como puedo hacer esto? Si alguíen tiene alguna idea de como puedo hacerlo o alguna alternativa, lo agradeceria. Gracias.
|
|
|
36
|
Programación / Scripting / Re: necesito ayuda con un problema en python soy nuevo en esto
|
en: 13 Noviembre 2021, 20:19 pm
|
import subprocess import optparse parser = optparse.OptionParser() parser.add_option("-i", "--interface", dest = "interface", help="Interface para cambiar Direccion MAC") parser.add_option("-m", "--mac", dest = "new_mac", help="Nueva Direccion MAC") (options, arguments) = parser.parse_args() interface = options.interface new_mac = options.new_mac print("Cambiando Direccion Mac para " + interface + " a " + new_mac) subprocess.call(["sudo ifconfig", interface, "down"]) subprocess.call(["sudo ifconfig", interface, "hw", "ether", new_mac]) subprocess.call(["sudo ifconfig", interface, "up"])
┌──(kali㉿kali)-[~] └─$ /usr/bin/python /home/kali/Documents/mac-changer.py 1 ⨯ Traceback (most recent call last): File "/home/kali/Documents/mac-changer.py", line 15, in <module> print("Cambiando Direccion Mac para " + interface + " a " + new_mac) TypeError: cannot concatenate 'str' and 'NoneType' objects MOD: Etiqueta GeSHiCuando quieres concatenar string con una variable, en python debes de convertir de la salida de esta variable en un string. Para poderlo hacer hay varias formas: metodo con str(): print("Cambiando Direccion Mac para " + str(interface) + " a " + str(new_mac))
metodo 2: print(f"Cambiando Direccion Mac para {interface} a {new_mac}")
Además veo que la salida de algunas de las variables devuelve None. Por eso te dice NoneType Recomendación al postear: Te recomiendo que al postear detalles lo más posible el problema. No se especifica que tipo de valores (string,int...) debe de retornar interface ni new_mac. Me imagino que es string pero no estoy seguro.
|
|
|
37
|
Programación / Scripting / Como obtengo los datos de la autorizacion (Basic Auth) en un request API | Python Django
|
en: 18 Septiembre 2021, 21:33 pm
|
Buenos dias, ¿como estais? Tengo un pequeño problemilla. Os cuento, estoy haciendo una API en Django [sin Django REST Framework ] y esta API el usuario puede utilizarla si se autentifica con metodo Basic Auth Donde pone Username es la Password Y donde pone password es el OTP Mi API hace esto: @csrf_exempt def requests(self,req,table:str,columns:list=False): try: try: if not loginAdmin(req.headers['password'], int(req.headers['otp'])): raise Exception("Access denied") except: raise Exception("You need authentication") conn = sqlite3.connect(Environment().pathDB()) cursor = conn.cursor()
es parte del codigo, pues yo estoy aqui seleccionando las keys password y otp del header, pero segun me he informado de que se muestra en el header en la key "Authorization" con encriptacion BASE64 https://learning.postman.com/docs/sending-requests/authorization/#basic-authPero yo he hecho return de req.headers y no hay ninguna key llamada "Authorization" o "Authorization", pero en el postman si se ve He estado buscando info y segun dicen si con req.META hay una HTTP_AUTHORIZATION, pero no se muestra ninguno GATEWAY_INTERFACESERVER_PROTOCOLREQUEST_METHODQUERY_STRINGREQUEST_URISCRIPT_NAMEPATH_INFOPATH_TRANSLATEDHTTP_HOSTHTTP_USER_AGENTHTTP_ACCEPT_ENCODINGHTTP_ACCEPTHTTP_CONNECTIONSERVER_SIGNATURESERVER_SOFTWARESERVER_NAMESERVER_ADDRSERVER_PORTREMOTE_ADDRDOCUMENT_ROOTREQUEST_SCHEMECONTEXT_PREFIXCONTEXT_DOCUMENT_ROOTSERVER_ADMINSCRIPT_FILENAMEREMOTE_PORTmod_wsgi.script_namemod_wsgi.path_infomod_wsgi.process_groupmod_wsgi.application_groupmod_wsgi.callable_objectmod_wsgi.request_handlermod_wsgi.handler_scriptmod_wsgi.script_reloadingmod_wsgi.listener_hostmod_wsgi.listener_portmod_wsgi.enable_sendfilemod_wsgi.ignore_activitymod_wsgi.request_startmod_wsgi.request_idmod_wsgi.script_startwsgi.versionwsgi.multithreadwsgi.multiprocesswsgi.run_oncewsgi.url_schemewsgi.errorswsgi.inputwsgi.input_terminatedwsgi.file_wrapperapache.versionmod_wsgi.versionmod_wsgi.total_requestsmod_wsgi.thread_idmod_wsgi.thread_requests
Aqui dejo la API: from sources import loginAdmin,Environment,logFile import sqlite3,re from django.urls import path from django.http import JsonResponse, HttpResponse, QueryDict from django.views.decorators.csrf import csrf_exempt """ ==========================API REST========================== SYNTAX: 127.0.0.1/api[/table,table1,table3,...][/column]?<key>=[>|<|>=|<=]<value>&[|]<key>=[>|<|>=|<=]<value>&LIMIT=<min>[,max] ============================================================ IMPORTANT: For do a request you need authentication with password and OTP EXAMPLES: GET: 127.0.0.1/api/server -> SELECT * FROM server 127.0.0.1/api/server?LIMIT=5 -> SELECT * FROM server LIMIT 5 127.0.0.1/api/server?password=ejem&id=1&LIMIT=5,7 -> SELECT * FROM server WHERE password='ejem' AND id=1 LIMIT 5,7 127.0.0.1/api/server/otp,id -> SELECT otp,id FROM server 127.0.0.1/api/server/otp?id=1&password=hola -> SELECT otp FROM server WHERE id=1 AND password='hola' 127.0.0.1/api/server/otp?id=1&|password=hola -> SELECT otp FROM server WHERE id=1 OR password='hola' POST: 127.0.0.1/api/server -> INSERT INTO server (otp,ejem) VALUES (1234,'1233da') Body x-www-form-urlencoded key value -------------------- otp 1234 ejem 1233da IMPORTANT: The params in the url doesn't affect PUT: 127.0.0.1/api/server?port=8899&|password=h -> UPDATE server SET otp='1234', ejem='1233da' WHERE port=8899 OR password='h' Body x-www-form-urlencoded key value -------------------- otp 1234 ejem 1233da DELETE: 127.0.0.1/api/server?port=8899&password=h -> DELETE FROM server WHERE port=8899 AND password='h' not body data """ class getData: def __init__(self,data): self.list = QueryDict(data) self.output = '' # This method returns key1,key2,key3... # For clause as SELECT, INSERT def getKeys(self): for t in self.list: self.output+=f'{t},' self.output = re.sub(r",$","",self.output) return self.output # This method returns value1,value2,value3... # For clause as SELECT, INSERT def getValues(self): for t in self.list: try: if int(self.list[t]): self.output+=f'{self.list[t]},' except: self.output += f"'{self.list[t]}'," self.output = re.sub(r",$","",self.output) return self.output # This method returns key1=value1, key2=value2, key3=value3 # being '=' the 'delimitator' # For clause as UPDATE def keysValues(self,delimitator): for value in self.list: self.output+=f"{value}{delimitator}'{self.list[value]}', " self.output = re.sub(r", $", "", self.output) return self.output class Database: # if there are columns, show it def columns(self,columns): if columns: return columns else: return "*" # This method add the operator specified in the url def keyWhere(self,key): operator = re.sub(r"[^>|<|=]","",key) value = re.sub(r"[>|<|=]","",key) if operator == "": operator="=" try: if int(value): return f"{operator}{value}" except: return f"{operator}'{value}'" def LimitClause(self,params): if params: output = '' for key in params: if key=="LIMIT": output=f" LIMIT {params[key]}" return output else: return "" # This method add AND or OR in each condition in WHERE def WhereClause(self,params): if params: output='' for key in params: if key=="LIMIT": continue operator = "OR" if key[0]=="|" else "AND" if list(params).index(key) > 0: output+=f" {operator} {key[1::] if operator=='OR' else key}{self.keyWhere(params[key])}" else: output += f"WHERE {key[1::] if operator=='OR' else key}{self.keyWhere(params[key])}" return output else: return "" @csrf_exempt def requests(self,req,table:str,columns:list=False): try: try: if not loginAdmin(req.headers['password'], int(req.headers['otp'])): raise Exception("Access denied") except: raise Exception("You need authentication") conn = sqlite3.connect(Environment().pathDB()) cursor = conn.cursor() if req.method == "GET": data = cursor.execute(f"SELECT {self.columns(columns)} FROM {table} {self.WhereClause(req.GET.dict())}{self.LimitClause(req.GET.dict())}") data = list(data) conn.close() if len(data) == 0: data = None return JsonResponse({ "result": data }) elif req.method == "POST": if columns: raise Exception("POST not allowed") cursor.execute(f"INSERT INTO {table} ({getData(req.body).getKeys()}) VALUES ({getData(req.body).getValues()})") conn.commit() conn.close() return JsonResponse({"INSERT":True}) elif req.method == "PUT": if columns: raise Exception("PUT not allowed") cursor.execute(f"UPDATE {table} SET {getData(req.body).keysValues('=')} {self.WhereClause(req.GET.dict())}") conn.commit() conn.close() return JsonResponse({"UPDATE": True}) elif req.method == 'DELETE': if columns: raise Exception("DELETE not allowed") cursor.execute(f"DELETE FROM {table} {self.WhereClause(req.GET.dict())}") conn.commit() conn.close() return JsonResponse({"DELETE": True}) except sqlite3.Error as err: return HttpResponse(logFile(True).message(f"DB -> {err}",True)) except Exception as err: return HttpResponse({f"Error in the API REST -> {err}"}) urlpatterns=[ path('<table>',Database().requests), path('<table>/<columns>',Database().requests) ]
¿Como yo puedo mostrar los datos del Auth? Muchas gracias. P.D: Cualquier comentario, sugerencia u opinion sobre la mejora del código, lo agradecería mucho. Mil gracias.
|
|
|
38
|
Programación / Scripting / Re: Ya voy 11 meses estudiando Python
|
en: 12 Septiembre 2021, 23:44 pm
|
@Panic0
Por lo general las librerías se aprenden en base a las necesidades que tengas. Si necesitas hacer una petición HTTP, te das cuenta que existe una librería muy buena llamada requests, pero luego te das cuenta que necesitas realizar peticiones asincrónicas, entonces ves que aiohttp es para ti. Quizá lo que necesites es procesar grandes cantidades de datos desde un CSV o una hoja de cálculo, entonces pandas puede ser para ti. Pero quizá necesites conectarte a una base de datos de MSSQL, entonces pyodbc es para ti, aunque quizá quieras algo más específico como el conector de MySQL o quizá SQLAlchemy dado que prefieres crear y mantener el esquema de las tablas con código de python o un estilo pythonista (un ORM, básicamente), o quizá quieras irte por una base de datos NOSQL como MongoDB, entonces mongoengine pueda adaptarse a ti. Quizá quieras combinar todo esto, pero también desees proporcionar una manera para que otras aplicaciones puedan conectarse con tus funcionalidades, entonces quizá te interese crear una API, lo cual puedes hacer con FastAPI, por ejemplo, o cualquier otro framework capaz.
Como ves, no es aprender siguiendo unos pasos, es algo muy dinámico.
~ DtxdF
Estoy de acuerdo en lo que dice @DtxdF, a medida que vayas haciendo proyectos veras diferentes librerias y sus funcionamientos. Si quieres aprender librerias orientadas a hacking etico, lo mejor es que hagas proyectos orientados a esta tematica, aquí te dejo unas cuantas: - Fuerza Bruta - Backdoor - Scrapping Web - Proxy server - keylogger - Ramsomware Son proyecto un tanto complejos, pero puedes empezar por algo básico como el Brute Force y Backdoor. Lo recomiendo hacerlos, para entender como funcionan estos tipos de malwares
|
|
|
40
|
Programación / Scripting / Acceder a una variable de una clase de un modulo python desde el exterior
|
en: 12 Septiembre 2021, 23:36 pm
|
. ├── ClassAdmin │ ├── ClassAdmin │ │ ├── __init__.py │ │ ├── settings.py │ │ ├── static │ │ │ ├── css │ │ │ │ ├── fonts.css │ │ │ │ ├── pageLogin.css │ │ │ │ └── styles.css │ │ │ ├── data.json │ │ │ ├── fonts │ │ │ │ └── Allura-Regular.ttf │ │ │ ├── images │ │ │ │ ├── ClassAdminLogo.png │ │ │ │ └── wallpaper.png │ │ │ └── js │ │ ├── templates │ │ │ ├── pageLogin.html │ │ │ └── src │ │ │ └── base.html │ │ ├── urls.py │ │ ├── views.py │ │ └── wsgi.py │ ├── ClassAdmin.sqlite3 │ └── manage.py └── sources └── __init__.py
Buenas, tengo un modulo llamado sources que es una carpeta con el archivo __init__.py, en el propio archivo esta la siguiente clase: class Environment: def __init__(self): self.directory = os.environ.get("CLASSADMIN") def pathDB(self): if platform.system() == "Windows": return f"{self.directory}\\ClassAdmin\\ClassAdmin.sqlite3" elif platform.system() == "Linux": return f"{self.directory}/ClassAdmin/ClassAdmin.sqlite3" def pathLog(self,name:str): if platform.system() == "Windows": return f"{self.directory}/{name}.log" elif platform.system() == "Linux": return f"/var/log/{name}.log"
Y desde el archivo settings.py haciendo el import quiero acceder a la variable directory que esta en el init de la clase Environment. from sources import * STATIC_ROOT = f'{Environment().directory}/ClassAdmin/ClassAdmin/static'
Pero esto me devuelve None [Errno 2] No such file or directory: 'None/ClassAdmin/ClassAdmin/static/data.json'
Porque pasa esto? si al hacer una clase con una variable self en el init puedes acceder a ella, no entiendo. Que esta ocurriendo? Gracias
|
|
|
|
|
|
|