Архив метки: Python

Python создание подпапки со всеми вышестоящими папками

from pathlib import Path
Path("/my/directory").mkdir(parents=True, exist_ok=True)

другой вариант:

import os
os.makedirs(target_dir, exist_ok=True)


pylint — установка и использование

pip install pylint

> python.exe -m pylint myscript.py
--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 0.00/10, +10.00)

Максимум 10 очков, чем больше тем лучше. Если есть замечания по коду — очки вычитаются.

Названия кодировок в Python

>>> from encodings.aliases import aliases
>>> print("%s" % aliases)
{'646': 'ascii', 'ansi_x3.4_1968': 'ascii', 'ansi_x3_4_1968': 'ascii', 'ansi_x3.4_1986': 'ascii', 'cp367': 'ascii', 'csascii': 'ascii', 'ibm367': 'ascii', 'iso646_us': 'ascii', 'iso_646.irv_1991': 'ascii', 'iso_ir_6': 'ascii', 'us': 'ascii', 'us_ascii': 'ascii', 'base64': 'base64_codec', 'base_64': 'base64_codec', 'big5_tw': 'big5', 'csbig5': 'big5', 'big5_hkscs': 'big5hkscs', 'hkscs': 'big5hkscs', 'bz2': 'bz2_codec', '037': 'cp037', 'csibm037': 'cp037', 'ebcdic_cp_ca': 'cp037', 'ebcdic_cp_nl': 'cp037', 'ebcdic_cp_us': 'cp037', 'ebcdic_cp_wt': 'cp037', 'ibm037': 'cp037', 'ibm039': 'cp037', '1026': 'cp1026', 'csibm1026': 'cp1026', 'ibm1026': 'cp1026', '1125': 'cp1125', 'ibm1125': 'cp1125', 'cp866u': 'cp1125', 'ruscii': 'cp1125', '1140': 'cp1140', 'ibm1140': 'cp1140', '1250': 'cp1250', 'windows_1250': 'cp1250', '1251': 'cp1251', 'windows_1251': 'cp1251', '1252': 'cp1252', 'windows_1252': 'cp1252', '1253': 'cp1253', 'windows_1253': 'cp1253', '1254': 'cp1254', 'windows_1254': 'cp1254', '1255': 'cp1255', 'windows_1255': 'cp1255', '1256': 'cp1256', 'windows_1256': 'cp1256', '1257': 'cp1257', 'windows_1257': 'cp1257', '1258': 'cp1258', 'windows_1258': 'cp1258', '273': 'cp273', 'ibm273': 'cp273', 'csibm273': 'cp273', '424': 'cp424', 'csibm424': 'cp424', 'ebcdic_cp_he': 'cp424', 'ibm424': 'cp424', '437': 'cp437', 'cspc8codepage437': 'cp437', 'ibm437': 'cp437', '500': 'cp500', 'csibm500': 'cp500', 'ebcdic_cp_be': 'cp500', 'ebcdic_cp_ch': 'cp500', 'ibm500': 'cp500', '775': 'cp775', 'cspc775baltic': 'cp775', 'ibm775': 'cp775', '850': 'cp850', 'cspc850multilingual': 'cp850', 'ibm850': 'cp850', '852': 'cp852', 'cspcp852': 'cp852', 'ibm852': 'cp852', '855': 'cp855', 'csibm855': 'cp855', 'ibm855': 'cp855', '857': 'cp857', 'csibm857': 'cp857', 'ibm857': 'cp857', '858': 'cp858', 'csibm858': 'cp858', 'ibm858': 'cp858', '860': 'cp860', 'csibm860': 'cp860', 'ibm860': 'cp860', '861': 'cp861', 'cp_is': 'cp861', 'csibm861': 'cp861', 'ibm861': 'cp861', '862': 'cp862', 'cspc862latinhebrew': 'cp862', 'ibm862': 'cp862', '863': 'cp863', 'csibm863': 'cp863', 'ibm863': 'cp863', '864': 'cp864', 'csibm864': 'cp864', 'ibm864': 'cp864', '865': 'cp865', 'csibm865': 'cp865', 'ibm865': 'cp865', '866': 'cp866', 'csibm866': 'cp866', 'ibm866': 'cp866', '869': 'cp869', 'cp_gr': 'cp869', 'csibm869': 'cp869', 'ibm869': 'cp869', '932': 'cp932', 'ms932': 'cp932', 'mskanji': 'cp932', 'ms_kanji': 'cp932', '949': 'cp949', 'ms949': 'cp949', 'uhc': 'cp949', '950': 'cp950', 'ms950': 'cp950', 'jisx0213': 'euc_jis_2004', 'eucjis2004': 'euc_jis_2004', 'euc_jis2004': 'euc_jis_2004', 'eucjisx0213': 'euc_jisx0213', 'eucjp': 'euc_jp', 'ujis': 'euc_jp', 'u_jis': 'euc_jp', 'euckr': 'euc_kr', 'korean': 'euc_kr', 'ksc5601': 'euc_kr', 'ks_c_5601': 'euc_kr', 'ks_c_5601_1987': 'euc_kr', 'ksx1001': 'euc_kr', 'ks_x_1001': 'euc_kr', 'gb18030_2000': 'gb18030', 'chinese': 'gb2312', 'csiso58gb231280': 'gb2312', 'euc_cn': 'gb2312', 'euccn': 'gb2312', 'eucgb2312_cn': 'gb2312', 'gb2312_1980': 'gb2312', 'gb2312_80': 'gb2312', 'iso_ir_58': 'gb2312', '936': 'gbk', 'cp936': 'gbk', 'ms936': 'gbk', 'hex': 'hex_codec', 'roman8': 'hp_roman8', 'r8': 'hp_roman8', 'csHPRoman8': 'hp_roman8', 'cp1051': 'hp_roman8', 'ibm1051': 'hp_roman8', 'hzgb': 'hz', 'hz_gb': 'hz', 'hz_gb_2312': 'hz', 'csiso2022jp': 'iso2022_jp', 'iso2022jp': 'iso2022_jp', 'iso_2022_jp': 'iso2022_jp', 'iso2022jp_1': 'iso2022_jp_1', 'iso_2022_jp_1': 'iso2022_jp_1', 'iso2022jp_2': 'iso2022_jp_2', 'iso_2022_jp_2': 'iso2022_jp_2', 'iso_2022_jp_2004': 'iso2022_jp_2004', 'iso2022jp_2004': 'iso2022_jp_2004', 'iso2022jp_3': 'iso2022_jp_3', 'iso_2022_jp_3': 'iso2022_jp_3', 'iso2022jp_ext': 'iso2022_jp_ext', 'iso_2022_jp_ext': 'iso2022_jp_ext', 'csiso2022kr': 'iso2022_kr', 'iso2022kr': 'iso2022_kr', 'iso_2022_kr': 'iso2022_kr', 'csisolatin6': 'iso8859_10', 'iso_8859_10': 'iso8859_10', 'iso_8859_10_1992': 'iso8859_10', 'iso_ir_157': 'iso8859_10', 'l6': 'iso8859_10', 'latin6': 'iso8859_10', 'thai': 'iso8859_11', 'iso_8859_11': 'iso8859_11', 'iso_8859_11_2001': 'iso8859_11', 'iso_8859_13': 'iso8859_13', 'l7': 'iso8859_13', 'latin7': 'iso8859_13', 'iso_8859_14': 'iso8859_14', 'iso_8859_14_1998': 'iso8859_14', 'iso_celtic': 'iso8859_14', 'iso_ir_199': 'iso8859_14', 'l8': 'iso8859_14', 'latin8': 'iso8859_14', 'iso_8859_15': 'iso8859_15', 'l9': 'iso8859_15', 'latin9': 'iso8859_15', 'iso_8859_16': 'iso8859_16', 'iso_8859_16_2001': 'iso8859_16', 'iso_ir_226': 'iso8859_16', 'l10': 'iso8859_16', 'latin10': 'iso8859_16', 'csisolatin2': 'iso8859_2', 'iso_8859_2': 'iso8859_2', 'iso_8859_2_1987': 'iso8859_2', 'iso_ir_101': 'iso8859_2', 'l2': 'iso8859_2', 'latin2': 'iso8859_2', 'csisolatin3': 'iso8859_3', 'iso_8859_3': 'iso8859_3', 'iso_8859_3_1988': 'iso8859_3', 'iso_ir_109': 'iso8859_3', 'l3': 'iso8859_3', 'latin3': 'iso8859_3', 'csisolatin4': 'iso8859_4', 'iso_8859_4': 'iso8859_4', 'iso_8859_4_1988': 'iso8859_4', 'iso_ir_110': 'iso8859_4', 'l4': 'iso8859_4', 'latin4': 'iso8859_4', 'csisolatincyrillic': 'iso8859_5', 'cyrillic': 'iso8859_5', 'iso_8859_5': 'iso8859_5', 'iso_8859_5_1988': 'iso8859_5', 'iso_ir_144': 'iso8859_5', 'arabic': 'iso8859_6', 'asmo_708': 'iso8859_6', 'csisolatinarabic': 'iso8859_6', 'ecma_114': 'iso8859_6', 'iso_8859_6': 'iso8859_6', 'iso_8859_6_1987': 'iso8859_6', 'iso_ir_127': 'iso8859_6', 'csisolatingreek': 'iso8859_7', 'ecma_118': 'iso8859_7', 'elot_928': 'iso8859_7', 'greek': 'iso8859_7', 'greek8': 'iso8859_7', 'iso_8859_7': 'iso8859_7', 'iso_8859_7_1987': 'iso8859_7', 'iso_ir_126': 'iso8859_7', 'csisolatinhebrew': 'iso8859_8', 'hebrew': 'iso8859_8', 'iso_8859_8': 'iso8859_8', 'iso_8859_8_1988': 'iso8859_8', 'iso_ir_138': 'iso8859_8', 'csisolatin5': 'iso8859_9', 'iso_8859_9': 'iso8859_9', 'iso_8859_9_1989': 'iso8859_9', 'iso_ir_148': 'iso8859_9', 'l5': 'iso8859_9', 'latin5': 'iso8859_9', 'cp1361': 'johab', 'ms1361': 'johab', 'cskoi8r': 'koi8_r', 'kz_1048': 'kz1048', 'rk1048': 'kz1048', 'strk1048_2002': 'kz1048', '8859': 'latin_1', 'cp819': 'latin_1', 'csisolatin1': 'latin_1', 'ibm819': 'latin_1', 'iso8859': 'latin_1', 'iso8859_1': 'latin_1', 'iso_8859_1': 'latin_1', 'iso_8859_1_1987': 'latin_1', 'iso_ir_100': 'latin_1', 'l1': 'latin_1', 'latin': 'latin_1', 'latin1': 'latin_1', 'maccyrillic': 'mac_cyrillic', 'macgreek': 'mac_greek', 'maciceland': 'mac_iceland', 'maccentraleurope': 'mac_latin2', 'maclatin2': 'mac_latin2', 'macintosh': 'mac_roman', 'macroman': 'mac_roman', 'macturkish': 'mac_turkish', 'ansi': 'mbcs', 'dbcs': 'mbcs', 'csptcp154': 'ptcp154', 'pt154': 'ptcp154', 'cp154': 'ptcp154', 'cyrillic_asian': 'ptcp154', 'quopri': 'quopri_codec', 'quoted_printable': 'quopri_codec', 'quotedprintable': 'quopri_codec', 'rot13': 'rot_13', 'csshiftjis': 'shift_jis', 'shiftjis': 'shift_jis', 'sjis': 'shift_jis', 's_jis': 'shift_jis', 'shiftjis2004': 'shift_jis_2004', 'sjis_2004': 'shift_jis_2004', 's_jis_2004': 'shift_jis_2004', 'shiftjisx0213': 'shift_jisx0213', 'sjisx0213': 'shift_jisx0213', 's_jisx0213': 'shift_jisx0213', 'tis260': 'tactis', 'tis620': 'tis_620', 'tis_620_0': 'tis_620', 'tis_620_2529_0': 'tis_620', 'tis_620_2529_1': 'tis_620', 'iso_ir_166': 'tis_620', 'u16': 'utf_16', 'utf16': 'utf_16', 'unicodebigunmarked': 'utf_16_be', 'utf_16be': 'utf_16_be', 'unicodelittleunmarked': 'utf_16_le', 'utf_16le': 'utf_16_le', 'u32': 'utf_32', 'utf32': 'utf_32', 'utf_32be': 'utf_32_be', 'utf_32le': 'utf_32_le', 'u7': 'utf_7', 'utf7': 'utf_7', 'unicode_1_1_utf_7': 'utf_7', 'u8': 'utf_8', 'utf': 'utf_8', 'utf8': 'utf_8', 'utf8_ucs2': 'utf_8', 'utf8_ucs4': 'utf_8', 'cp65001': 'utf_8', 'uu': 'uu_codec', 'zip': 'zlib_codec', 'zlib': 'zlib_codec', 'x_mac_japanese': 'shift_jis', 'x_mac_korean': 'euc_kr', 'x_mac_simp_chinese': 'gb2312', 'x_mac_trad_chinese': 'big5'}

python3 xmlrpc

import xmlrpc.client as xc
client = xc.Server('http://' + host + ':' + port + '/RPC2')
client.supervisor.getState()
client.supervisor.getProcessInfo('process name')

>>> import xmlrpc.client as xc
>>> client = xc.Server("http://127.0.0.1:8000/trac_test/rpc")
>>> client.system.listMethods()

Черновик консольной программы для разбора бардака на компьютере (Python)

План был такой:

  1. Выбрать папку для разбора бардака
  2. Программа будет по очереди показывать оттуда файлы (фотки, видео и т.д.)
  3. Пользователь через пробел вводит теги для просмотренного файла (например «фото машина зима» или просто «trash»)
  4. программа переходит к следующему файлу, пока список не кончится
  5. В результате формируется база данных по файлам (sqlite files.db)
  6. Тэги привязываются не к пути файла, а к его контрольной сумме MD5, если копия папки попадётся где-то ещё — программа файлы узнает
  7. В результате файлы любого типа можно находить по тегам
  8. Для удаления мусора можно составить список файлов например с тегом «trash» и передать список например команде «del»

Главное меню:

                Программа для разбора бардака с файлами
                1. Выбор папки
                2. Анализ
                3. Разбор
                4. Сохранить списки
                
                0. Выход

Исходный код черновика (написано за 2 дня):

#! -*- coding: utf-8 -*-

'''
Программа для разбора бардака на дисках

LOG:
    добавил ввод нескольких тэгов через пробел
    добавил таблицу с путями к файлам
    добавил просмотр видео
    добавил разбор по выбранному тэгу, можно для просмотра
    добавил вывод текущих тегов
    добавил удаление тегов через -...
'''

import os
import sqlite3
import hashlib
import time

# просмотрщики
IMAGE_PROGRAM = "eog"
VIDEO_PROGRAM = "vlc"
MUSIC_PROGRAM = "vlc"
TEXT_PROGRAM = "gedit"

CREATE_TABLES_QUERY = """
CREATE TABLE `FILES_INFO` ( `FILES_INFO_ID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, `PATH` TEXT NOT NULL, `FILE_MD5` TEXT NOT NULL, `LAST_MODIFIED` TEXT )

CREATE TABLE `FILES_TAGS` ( `FILES_TAGS_ID` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT UNIQUE, `FILE_MD5` TEXT NOT NULL, `TAG` TEXT NOT NULL )
"""

class FilesAnalyzer:
    
    def __init__(self):
        self.db_connection = sqlite3.connect('files.db')
        self.path = ''
        self.count_by_tags = {}
        self.files_by_tags = {}
        
    def analyze(self):
        '''
        1. Статистика по количеству файлов по каждому тегу
        и неразмеченных
        2. Сохранение списков файлов по каждому тегу
        и неразмеченных
        '''
        # Счётчики файлов по тегам
        self.count_by_tags = {}
        self.count_by_tags[""] = 0
        
        # списки файлов по тегам
        self.files_by_tags = {}
        self.files_by_tags[""] = []
        
        for root, dirs, files in os.walk(self.path):
            for f in files:
                f_full = '%s/%s' % (root, f)
                f_md5 = self.get_md5(f_full)
                f_tags = self.get_tags(f_md5)
                ''' DEBUG
                print('Файл: %s' % f_full)
                print('MD5: %s' % f_md5)
                print('Тэги: %s' % ', '.join(f_tags))
                '''
                if len(f_tags) > 0:
                    for tag in f_tags:
                        if tag not in self.count_by_tags.keys():
                            self.count_by_tags[tag] = 1
                            self.files_by_tags[tag] = []
                            self.files_by_tags[tag].append(f_full)
                        else:
                            self.count_by_tags[tag] += 1
                            self.files_by_tags[tag].append(f_full)
                else:
                    self.count_by_tags[''] += 1
                    self.files_by_tags[''].append(f_full)
        for key in self.count_by_tags.keys():
            print("Тэг '%s': %s" % (key, self.count_by_tags[key]))
        ''' DEBUG
        for key in self.files_by_tags.keys():
            print("Файлы '%s':" % key)
            for f in self.files_by_tags[key]:
                print(f)
        '''
        
    def manual_sort(self, selected_tag=""):
        '''
        Ручная маркировка тегами неразмеченных файлов
        '''
        if selected_tag in self.files_by_tags.keys():
            for f in self.files_by_tags[selected_tag]:
                # проверить что новый md5
                md5 = self.get_md5(f)
                tags = self.get_tags(md5)
                if (selected_tag == "" and len(tags) == 0) \
                        or selected_tag in tags:
                    print("Файл: '%s'" % f)
                    print("Текущие тэги: %s" % \
                            self.get_tags(md5))
                    # пердосмотр или открыть файл
                    self.try_preview(f)
                    new_tags_text = input("Введи тэги для файла: ")
                    if len(new_tags_text) > 0:
                        new_tags = new_tags_text.split()
                        for new_tag in new_tags:
                            self.save_tag(f, new_tag)
                        self.save_info(f)
            # теперь прошлый анализ бесполезен
            self.files_by_tags = {}
            self.count_by_tags = {}
        else:
            print('Ошибка: файлов с тегом "%s" не найдено' % selected_tag)
            
    def save_info(self, f):
        '''
        сохранение информации о файле в БД
        /param[in] f - имя файла
        '''
        # приготовить информацию
        md5 = self.get_md5(f)
        mtime = os.path.getmtime(f)
        last_modified = time.strftime('%Y-%m-%d %H:%M:%S',
                time.localtime(mtime))
        
        # проверить, что в базе такого ещё нет
        cur = self.db_connection.cursor()
        check_query = """SELECT * 
                FROM FILES_INFO
                WHERE PATH = '%s'
                AND FILE_MD5 = '%s'
                AND LAST_MODIFIED = '%s'""" % (
                f, md5, last_modified)
        is_new = True
        for row in cur.execute(check_query):
            is_new = False
        
        if is_new:
            # сохранение в БД
            query = """INSERT INTO FILES_INFO
            (PATH, FILE_MD5, LAST_MODIFIED)
            VALUES ('%s', '%s', '%s')""" % (
            f, md5, last_modified)
            cur.execute(query)
            self.db_connection.commit()
        
    def try_preview(self, f):
        if f.lower()[-4:] in ('.png', '.bmp', '.gif', '.jpg', 'jpeg'):
            #os.system('eog "%s"' % f)
            os.system('%s "%s"' % (IMAGE_PROGRAM, f))
        elif f.lower()[-4:] in ('.avi', '.mpg', '.3gp', '.mov'):
            os.system('%s "%s"' % (VIDEO_PROGRAM, f))
        elif f.lower()[-4:] in ('.mp3', '.wav', '.ogg'):
            os.system('%s "%s"' % (MUSIC_PROGRAM, f))
        
        
    def save_tag(self, f, tag):
        md5 = self.get_md5(f)
        cur = self.db_connection.cursor()
        if tag[0] == "-":
            # TODO: УДАЛИТЬ ТЕГ
            del_query = """DELETE FROM FILES_TAGS
                    WHERE FILE_MD5 = '%s'
                    AND TAG = '%s'""" % (md5, tag[1:])
            cur.execute(del_query)
            self.db_connection.commit()
        else:
            # Сначала проверить что тега у файла ещё нет
            check_query = """SELECT * FROM FILES_TAGS
                    WHERE FILE_MD5 = '%s'
                    AND TAG = '%s'""" % (md5, tag)
            is_new = True
            for row in cur.execute(check_query):
                is_new = False
                break
            
            if is_new:
                # Добавить файлу тег
                query = """INSERT INTO FILES_TAGS
                        (FILE_MD5, TAG) VALUES ('%s', '%s')""" % (
                        md5, tag)
                cur.execute(query)
                self.db_connection.commit()
            
    def show_main_menu(self):
        while True:
            print('\n' * 3 + '''
                Программа для разбора бардака с файлами
                1. Выбор папки
                2. Анализ
                3. Разбор
                4. Сохранить списки
                
                0. Выход
            ''')
            
            selected = input("Что делать? > ")
            if selected == "0":
                self.close()
            elif selected == "1":
                self.show_select_path_menu()
            elif selected == "2":
                self.show_analyze_menu()
            elif selected == "3":
                self.show_manual_sort_menu()
            elif selected == "4":
                self.show_save_lists_menu()
            
    def close(self):
        self.db_connection.close()
        print("Выход из программы")
        quit()

    def show_save_lists_menu(self):
        print("Сохранение списков файлов")
        self.save_lists()
        
    def save_lists(self):
        for key in self.files_by_tags.keys():
            file_name = "%s.txt" % key
            if key == "":
                file_name = "_unsorted.txt"
            if len(self.files_by_tags[key]) > 0:
                f = open(file_name, 'w')
                for item in self.files_by_tags[key]:
                    f.write(item)
                    f.write('\n')
                f.close()
                print(file_name)
    
    def show_select_path_menu(self):
        selected = input('Введите имя папки для разбора: ')
        if self.is_valid_path(selected):
            self.path = selected
            print("Выбрана папка: '%s'" % selected)
        else:
            print("Ошибка: не удалось выбрать папку: '%s'" % selected)
        
    def show_analyze_menu(self):
        print("Анализ файлов в %s:" % self.path)
        self.analyze()
    
    def show_manual_sort_menu(self):
        print("Ручной разбор файлов")
        selected_tag = input("Выбери тег для разбора (по умолчанию без тегов): ")
        self.manual_sort(selected_tag)
    
    def is_valid_path(self, str_path):
        if os.path.exists(str_path):
            return True
        else:
            return False
            
    def get_md5(self, file_path):
        result = ''
        f = open(file_path, 'rb')
        content = f.read()
        f.close()
        result = hashlib.md5(content).hexdigest()
        return result
    
    def get_tags(self, md5):
        result = []
        
        cur = self.db_connection.cursor()
        query = "SELECT TAG FROM FILES_TAGS WHERE FILE_MD5 = '%s'" % md5
        for row in cur.execute(query):
            result.append(row[0])
        return result
    
if __name__ == "__main__":
    fa = FilesAnalyzer()
    fa.show_main_menu()