Форум сайта python.su
0
Итак есть входные данные в виде текстовика типа
ThreadDiam. Pitch HoleDiam. M DESC_IN_DRAFTING 2mm 0,4mm 1,567mm M2 2,5mm 0,45mm 2,013mm M2,5 3mm 0,5mm 2,459mm M3 4mm 0,7mm 3,242mm M4
<?xml version="1.0" ?> <!-- --> <!-- ******************************************************************* --> <!-- * Standard Metric_Thin_Pitch * --> <!-- ******************************************************************* --> <std:node name="Thread_standard" xmlns:std="http://www.dsweb.com/std"> <std:node name="Key"> <std:strval name="Key">M</std:strval> <std:strval name="KeyDrafting">NO_DESC_IN_DRAFTING</std:strval> </std:node> <std:typedef name="Standard"> <std:floatval name="ThreadDiameter">0.0</std:floatval> <std:floatval name="Pitch">1.0</std:floatval> <std:floatval name="NominalDiameter">0.13</std:floatval> <std:strval name="Description">M8</std:strval> </std:typedef> <std:node name="Values"> <std:typeval name="Standard"> <std:floatval name="ThreadDiameter">8.0</std:floatval> <std:floatval name="Pitch">1.0</std:floatval> <std:floatval name="NominalDiameter">6.917</std:floatval> <std:strval name="Description">M8x1</std:strval> </std:typeval> <std:typeval name="Standard"> <std:floatval name="ThreadDiameter">10.0</std:floatval> <std:floatval name="Pitch">1.0</std:floatval> <std:floatval name="NominalDiameter">8.917</std:floatval> <std:strval name="Description">M10x1</std:strval> </std:typeval> <std:typeval name="Standard"> <std:floatval name="ThreadDiameter">10.0</std:floatval> <std:floatval name="Pitch">1.25</std:floatval> <std:floatval name="NominalDiameter">8.647</std:floatval> <std:strval name="Description">M10x1.25</std:strval> </std:typeval> </std:node> </std:node>
# -*- coding: utf-8 -*- ''' Утилита для переноса стандартов резьбы. Разработана и оттестирована на Catia V5R22sp3 ThreadConverter.py input_file output_file dots_flag \tinput_file -\tпуть с указанием файла для конвертации, \t\t\tформат файла текстовый, кодировка не принципиальна, \t\t\tрасширение тоже. \toutput_file -\tпуть с указанием файла для записи, \t\t\tформат файла xml. \tdots_flag-\tTrue or False \t\t\tЗамена decimal separator в output_file \t\t\tif dots_flag: \t\t\t\tdecimal separator = '.' \t\t\telse: \t\t\t\tdecimal separator = ',' Тестировалось на CatiaV5R22. Конвертировались стандарты с сайта http://www.plm-forum.ru/forum/ Created on 13.02.2013 @author: Бирюков ''' from sys import argv from sys import exit try: i_file, o_file, dots = argv[1:] except ValueError: print(__doc__) print('Неверно заданы аргументы!') input('Press any key to exit...') exit('Terminated...') ppprint = False try: from lxml import etree as etree print('from lxml import etree as etree') ppprint = True except ImportError: try: from xml.etree import cElementTree as etree print('from xml.etree import cElementTree as etree') ppprint = False except ImportError: try: from xml.etree import ElementTree as etree print('from xml.etree import ElementTree as etree') ppprint = False except ImportError: exit('Импортирование провалилось.\nИсправьте зависимости!') class SameFileExeption(Exception): ''' Простой класс для ошибок. Пока не используется;) ''' def __str__(self, *args, **kwargs): return repr(self.value) def __init__(self, msg): self.value = msg class ThreadConverterClass: ''' Зависимости: lxml, возможно будет работать без оной, не тестировалось Класс для конвертирования стандарта резьбы в стиле CatiaV5R20 и более ранних релизов в стандарт CatiaV5R21 и старше, включая, предположительно, V6. input_file -\tпуть с указанием файла для конвертации, \tinput_file -\tпуть с указанием файла для конвертации, \t\t\tформат файла текстовый, кодировка не принципиальна, \t\t\tрасширение тоже. \toutput_file -\tпуть с указанием файла для записи, \t\t\tформат файла xml. \tdots_flag-\tTrue or False \t\t\tЗамена decimal separator в output_file \t\t\tif dots_flag: \t\t\t\tdecimal separator='.' \t\t\telse: \t\t\t\tdecimal separator=',' Тестировалось на CatiaV5R22. Конвертировались стандарты с сайта http://www.plm-forum.ru/forum/ ''' # input_file = 'input_file.txt' # output_file = 'output_file.xml' # enable_dots = True def eq_block(self, elem, name_spase, T, P, N, D): sub_elem = etree.SubElement(elem, name_spase + 'floatval') sub_elem.set('name', 'ThreadDiameter') sub_elem.text = T sub_elem = etree.SubElement(elem, name_spase + 'floatval') sub_elem.set('name', 'Pitch') sub_elem.text = P sub_elem = etree.SubElement(elem, name_spase + 'floatval') sub_elem.set('name', 'NominalDiameter') sub_elem.text = N sub_elem = etree.SubElement(elem, name_spase + 'strval') sub_elem.set('name', 'Description') sub_elem.text = D return def typedef_block(self, elem, name_spase, T, P, N, D): sub_elem = etree.SubElement(elem, name_spase + 'typedef') sub_elem.set('name', 'Standard') self.eq_block(sub_elem, name_spase, T, P, N, D) return def typeval_block(self, elem, name_spase, T, P, N, D): sub_elem = etree.SubElement(elem, name_spase + 'typeval') sub_elem.set('name', 'Standard') self.eq_block(sub_elem, name_spase, T, P, N, D) return def ThreadStdGenerator(self, input_file, output_file, enable_dots=True): # получение имени выходного файла # output_file = input_file[:-4] + '.xml' # XML_NAMESPACE XML_NAMESPACE = 'http://www.dsweb.com/std' # PREFIX PREFIX = '{%s}' % XML_NAMESPACE # NSMAP не стандарт NSMAP = {'std': XML_NAMESPACE} # lxml only! xml_root = etree.Element(PREFIX + 'node', nsmap=NSMAP) xml_root.set('name', 'Thread_standard') #====================================================================== # <std:node name="Key"> # <std:strval name="Key">M</std:strval> # <std:strval name="KeyDrafting">NO_DESC_IN_DRAFTING</std:strval> # </std:node> #====================================================================== block_key = etree.SubElement(xml_root, PREFIX + 'node') # <std:node name="Key"> block_key.set('name', 'Key') # <std:strval name="Key">M</std:strval> block_key_subkey = etree.SubElement(block_key, PREFIX + 'strval') block_key_subkey.set('name', 'Key') block_key_subkey.text = 'M' # <std:strval name="KeyDrafting">NO_DESC_IN_DRAFTING</std:strval> block_key_draft = etree.SubElement(block_key, PREFIX + 'strval') block_key_draft.set('name', 'KeyDrafting') block_key_draft.text = 'NO_DESC_IN_DRAFTING' #====================================================================== # <std:typedef name="Standard"> # <std:floatval name="ThreadDiameter">0.0</std:floatval> # <std:floatval name="Pitch">1.0</std:floatval> # <std:floatval name="NominalDiameter">0.13</std:floatval> # <std:strval name="Description">M8</std:strval> # </std:typedef> #====================================================================== self.typedef_block(xml_root, PREFIX, '0.0', '1.0', '0.13', 'M8') block_value_data = etree.SubElement(xml_root, PREFIX + 'node') block_value_data.set('name', 'Values') with open(input_file, 'r') as f_input: data_lines = f_input.readlines() data_header_std = ['ThreadDiam', 'Pitch', 'HoleDiam', 'Minordiam', 'M'] rslt = False for txt in data_header_std: if txt in data_lines[0]: rslt = True else: rslt = False if rslt: data_lines.remove(data_lines[0]) else: print("Нет заголовка") for line in data_lines: if enable_dots: line = line.replace(',', '.') ln = line.split('\t') self.typeval_block(block_value_data, PREFIX, ln[0], ln[1], ln[2], ln[3]) with open(output_file, 'wb') as f_output: b_comment = etree.Comment(text='*' * 20) if ppprint: f_output.write(etree.tostring(xml_root, pretty_print=True, encoding='utf-8', xml_declaration=True, doctype=b_comment.__str__() ) ) else: etree.ElementTree(xml_root).write(output_file, encoding='utf-8', xml_declaration=True, method='xml' ) return def __init__(self, input_file='.txt', output_file='.xml', enable_dots=True): ''' Constructor ''' self.input_file = input_file self.output_file = output_file self.enable_dots = enable_dots self.ThreadStdGenerator(self.input_file, self.output_file, self.enable_dots ) if __name__ == '__main__': print('Script: '+argv[0]) if i_file == o_file: exit('Входной и выходной файлы должны различаться!\nTerminated....') input('>>>') print('input_data=', i_file) print('output_data=', o_file) try: ThreadConverterClass(i_file, o_file, dots) print('Конвертация прошла успешно!') input('Press any key to exit...') except: exit('Конвертация не удалась!') input('Press any key to exit...')
<!-- --> <!-- ******************************************************************* --> <!-- * Standard Metric_Thin_Pitch * --> <!-- ******************************************************************* -->
Офлайн
0
PS:Еще не реализованная функция- при изменении аргументов класса пересчитывать выходные данные
реализовать функцию записи данных класса.
сожно сказать это моя первая более менее работающая программа, Класс задумал больше для тренировки, чем для надобности
Офлайн
173
SHDWetree.Comment()
1. как вывести коммент
root = ... comments = ( """******************************************************************* * Standard Metric_Thin_Pitch * *******************************************************************""" ) for line in comments.splitlines(): root.addprevious(etree.Comment(line))
SHDWПосмотрите в сторону http://lxml.de/api/lxml.builder.ElementMaker-class.html
2. тк новичек в python приму ллюбую критику
# -*- coding: utf-8 -*- from lxml import etree from lxml.builder import ElementMaker XML_NAMESPACE = 'http://www.dsweb.com/std' NSMAP = {'std': XML_NAMESPACE} E = ElementMaker(namespace=XML_NAMESPACE, nsmap=NSMAP) def A(node, *children): """ Добавляет дочерние элементы к `node` возвращает `node` """ if len(children) == 1 and isinstance(children[0], (list, tuple)): children = children[0] for child in children: node.append(child) return node def eq_block(T, P, N, D): return ( E.floatval(T, name='ThreadDiameter'), E.floatval(P, name='Pitch'), E.floatval(N, name='NominalDiameter'), E.strval(D, name='Description'), ) root = ( A(E.node(name='Thread_standard'), A(E.node(name='Key'), E.strval('M', name='Key'), E.strval('NO_DESC_IN_DRAFTING', name='KeyDrafting'), ), A(E.typedef(name="Standard"), eq_block('0.0', '1.0', '0.13', 'M8')), A(E.node(name="Values"), # вместо этих двух записей - генератор значений из файла A(E.typeval(name="Standard"), eq_block('0.0', '1.0', '0.13', 'M8')), A(E.typeval(name="Standard"), eq_block('0.0', '1.0', '0.13', 'M8')), ) ) ) tree = etree.ElementTree(root) comments = ( """******************************************************************* * Standard Metric_Thin_Pitch * *******************************************************************""" ) for line in comments.splitlines(): root.addprevious(etree.Comment(line)) print(etree.tostring(tree, pretty_print=True, xml_declaration=True, encoding='utf-8'))
SHDWНе совсем понятно, чего хотите добиться. Но если бы для чтения данных, создания дерева и сохранения дерева в файл были отдельные функции (и генераторы), было бы проще.
Еще не реализованная функция- при изменении аргументов класса пересчитывать выходные данные
реализовать функцию записи данных класса.
Отредактировано reclosedev (Фев. 18, 2013 18:39:11)
Офлайн
0
Посмотрите в сторону http://lxml.de/api/lxml.builder.ElementMaker-class.htmlочень интересное решение, не нашел по первой в документации про префиксы…и второе мой код работает впринципе и без lxml, что для конечного пользователя лучше.
Код с ним получается короче, так как не нужно писать префиксы и можно задавать атрибуты и значения в конструкторе. А с помощью функций-помощников выходит почти в декларативном стиле:
for f in filelist: a =class(file) if a.result_status: a.write()
Офлайн
173
SHDWЯ имел ввиду не отказ от классов (хотя здесь без них спокойно можно обойтись), а разделение метода ThreadStdGenerator() на несколько.
Соглашусь, что вы правы, используя функции было бы короче,но я решил потренироваться на
кошках классах.
SHDWСогласен. Но с другой стороны, Catia это ведь для Windows? А для конечного пользователя win удобнее exe, сделанный cx_freeze или подобным.
и второе мой код работает впринципе и без lxml, что для конечного пользователя лучше.
Отредактировано reclosedev (Фев. 19, 2013 16:45:54)
Офлайн
0
reclosedevпоследнее время да, но есть unix версии и пара других поддерживаемых платформ
Согласен. Но с другой стороны, Catia это ведь для Windows? А для конечного пользователя win удобнее exe, сделанный cx_freeze или подобным.
def foo(bar) bar=4 return
isinstance(children[0], (list, tuple))
Офлайн
173
SHDWСначала советую прочитать про типы в wiki
Правильно ли я понимаю, что внутрь функции передается экземпляр переменной. А над самой и все действия производится над переменной и после выхода из функции экземпляр уничтожается?
Все объекты делятся на ссылочные и атомарные. К атомарным относятся int, long, complex и некоторые другие. При присваивании атомарных объектов копируется их значение, в то время как для ссылочных копируется только указатель на объект, таким образом, обе переменные после присваивания используют одно и то же значение. Ссылочные объекты бывают изменяемые и неизменяемые. Например, строки и кортежи являются неизменяемыми, а списки, словари и многие другие объекты — изменяемыми. Кортеж в Питоне является, по сути, неизменяемым списком.и еще про ссылки
SHDWhttp://docs.python.org/3.3/library/functions.html#isinstance
А эта функциЯ проверяет является ли children списком или кортежем?
children[0]
Офлайн
0
reclosedevЭто стало понятно, просто в разных языках по разному называются, хотя смысл одинаковый.
Сначала советую прочитать про типы в wiki
Офлайн
16
При присваивании атомарных объектов копируется их значение, в то время как для ссылочных копируется только указатель на объект, таким образом, обе переменные после присваивания используют одно и то же значение.
>>> a = 5
>>> b = a
>>> id(a)
507081344
>>> id(b)
507081344
>>> id(5)
507081344
Офлайн
0
Все узнается опытным путем:) как обычно одним словом.
Заметь, если ты изменишь а, b не изменится, те его значение скопировалось.
Но если подобное сделать со списком, то ситуация буден несколько иной, покрайней мере в 3 версии
Отредактировано SHDW (Фев. 22, 2013 11:34:06)
Офлайн