Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Скриптовые языки программирования > Python
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 22.12.2023, 10:59   #1
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию Код, который делает замены в коде Python при помощи C

здравствуйте, нейросеть подсказала:
Вот код, который делает замены txt = txt.replace(l, tr) в коде Python при помощи C:
Код:
import cffi # pip install -U cffi
from cffi.backends import ctypes as ffi
ffi = cffi.FFI()
ffi.cdef("""char *replace(char *txt, char *l, char *tr);""")
ffi.set_source("my_module", """#include <stdio.h>
char *replace(char *txt, char *l, char *tr) {
  char *p = txt;
  while ((p = strstr(p, l)) != NULL) {
    memmove(p + strlen(tr), p + strlen(l), strlen(p + strlen(l)) - strlen(l) + 1);
    memcpy(p, tr, strlen(tr));
  }
  return txt;
}
""")

ffi.compile()
txt = "Это строка. Это еще одна строка."
l = "строка"
tr = "текст"

replace_func = ffi.get_symbol(ffi.get_library("my_module"), "replace")
replaced_txt = ffi.string(replace_func(ffi.new("char[]", txt), ffi.new("char[]", l), ffi.new("char[]", tr)))

print(replaced_txt)
Этот код работает следующим образом:

Инициализируется библиотека CFFI.
Определяется прототип функции replace().
Компилируется C-код, содержащий функцию replace().
Создаются указатели на строки txt, l и tr.
Функция ffi.get_symbol() используется для получения указателя на функцию replace() из библиотеки my_module.
Функция replace() вызывается с параметрами txt, l и tr.
Функция ffi.string() используется для преобразования результата вызова функции replace() в строку.
В результате выполнения этого кода будет выведен следующий текст:

Это текст. Это еще один текст.
опробовав его получаю ошибку
ModuleNotFoundError: No module named 'cffi.backends'
подскажите как её исправить? будет ли смысл в этом огороде при необходимости сделать миллион замен в тексте?
Ципихович Эндрю вне форума Ответить с цитированием
Старый 22.12.2023, 21:13   #2
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

У меня на 3 питоне заработало только в таком виде:
Код:
from cffi import FFI

ffi = FFI()
ffi.cdef("""char *replace(char *txt, char *l, char *tr);
wchar_t *wreplace(wchar_t *txt, wchar_t *l, wchar_t *tr);
""")
ffi.set_source("my_module", """#include <stdio.h>

char *replace(char *txt, char *l, char *tr) {
  char *p = txt;
  while ((p = strstr(p, l)) != NULL) {
    memmove(p + strlen(tr), p + strlen(l), strlen(p + strlen(l)) + 1);
    memcpy(p, tr, strlen(tr));
    p += strlen(tr);
  }
  return txt;
}

wchar_t *wreplace(wchar_t *txt, wchar_t *l, wchar_t *tr) {
  wchar_t *p = txt;
  while ((p = wcsstr(p, l)) != NULL) {
    wmemmove(p + wcslen(tr), p + wcslen(l), wcslen(p + wcslen(l)) + 1);
    wmemcpy(p, tr, wcslen(tr));
    p += wcslen(tr);
  }
  return txt;
}
""")

ffi.compile()

from my_module import ffi, lib

txt = b"Hello world"
l = b"Hello"
tr = b"Bye"
print(ffi.string(lib.replace(ffi.new("char[]", txt), ffi.new("char[]", l), ffi.new("char[]", tr))))

txt = "Это строка. Это еще одна строка."
l = "строка"
tr = "текст"
print(ffi.string(lib.wreplace(ffi.new("wchar_t[]", txt), ffi.new("wchar_t[]", l), ffi.new("wchar_t[]", tr))))

import timeit

print(timeit.timeit('ffi.string(lib.wreplace(ffi.new("wchar_t[]", txt), ffi.new("wchar_t[]", l), ffi.new("wchar_t[]", tr)))', globals = globals()))
print(timeit.timeit('txt.replace(l, tr)', globals = globals()))
Замечание по C-коду, такой способ замены безопасен только при замене более длинной подстроки на более короткую, иначе будет переполнение строки, т.к. память под лишние символы никто не выделял. В таком виде C-вариант в 8 раз медленнее, чем обычный replace. Возможно, если махом передать все замены и получить один раз новую строку, то какой-то толк будет.
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Старый 22.12.2023, 21:36   #3
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

BDA, спасибо!!, работает

Последний раз редактировалось Ципихович Эндрю; 22.12.2023 в 21:55.
Ципихович Эндрю вне форума Ответить с цитированием
Старый 22.12.2023, 21:38   #4
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

BDA, по мотивам вашего кода, для большей ясности код:
Код:
import timeit
from cffi import FFI
ffi = FFI()
ffi.cdef("""char *replace(char *txt, char *l, char *tr);wchar_t *wreplace(wchar_t *txt, wchar_t *l, wchar_t *tr);""")
ffi.set_source("my_module", """#include <stdio.h>
char *replace(char *txt, char *l, char *tr) {
  char *p = txt;
  while ((p = strstr(p, l)) != NULL) {
    memmove(p + strlen(tr), p + strlen(l), strlen(p + strlen(l)) + 1);
    memcpy(p, tr, strlen(tr));
    p += strlen(tr);
  }
  return txt;
}

wchar_t *wreplace(wchar_t *txt, wchar_t *l, wchar_t *tr) {
  wchar_t *p = txt;
  while ((p = wcsstr(p, l)) != NULL) {
    wmemmove(p + wcslen(tr), p + wcslen(l), wcslen(p + wcslen(l)) + 1);
    wmemcpy(p, tr, wcslen(tr));
    p += wcslen(tr);
  }
  return txt;
}""")

ffi.compile()

from my_module import ffi, lib

txt = "Это строка. Это еще одна строка."
l = "строка"
tr = "текст"

# Benchmark the CFFI replacement method
ffi_time = timeit.timeit('ffi.string(lib.wreplace(ffi.new("wchar_t[]", txt), ffi.new("wchar_t[]", l), ffi.new("wchar_t[]", tr)))', globals = globals(), number=100)
print("FFI Replacement Time:", ffi_time)

# Benchmark the Python replacement method
python_time = timeit.timeit('txt.replace(l, tr)', globals = globals(), number=100)
print("Python Replacement Time:", python_time)

if ffi_time < python_time:
    print("FFI replacement is faster=замена происходит быстрее")
else:
    print("Python replacement is faster=замена происходит быстрее")
у меня вывело:
FFI Replacement Time: 0.0004976999989594333
Python Replacement Time: 5.310000051395036e-05
Python replacement is faster=замена происходит быстрее
всё было зря?

Последний раз редактировалось Ципихович Эндрю; 22.12.2023 в 22:00.
Ципихович Эндрю вне форума Ответить с цитированием
Старый 22.12.2023, 21:59   #5
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

Цитата:
Сообщение от BDA Посмотреть сообщение
Возможно, если махом передать все замены и получить один раз новую строку, то какой-то толк будет.
это как? не понял эту мысль?
Ципихович Эндрю вне форума Ответить с цитированием
Старый 22.12.2023, 22:05   #6
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

Цитата:
Сообщение от Ципихович Эндрю Посмотреть сообщение
это как? не понял эту мысль?
нейросеть подсказала:
Код:
import timeit

import cffi

# Import the CFFI library
ffi = cffi.FFI()

# Define the CFFI types
ffi.cdef("""
typedef char *char_ptr;
typedef wchar_t *wchar_ptr;

char *replace(char *txt, char *l, char *tr, int len);
wchar_t *wreplace(wchar_t *txt, wchar_ptr *l, wchar_ptr *tr, int len);
""")

# Set the source code for the CFFI library
ffi.set_source("my_module", """
#include <stdio.h>

char *replace(char *txt, char *l, char *tr, int len) {
  char *p = txt;
  for (int i = 0; i < len; i++) {
    memmove(p + strlen(*tr), p + strlen(*l), strlen(p + strlen(*l)) + 1);
    memcpy(p, *tr, strlen(*tr));
    p += strlen(*tr);
  }
  return txt;
}

wchar_t *wreplace(wchar_t *txt, wchar_ptr *l, wchar_ptr *tr, int len) {
  wchar_t *p = txt;
  for (int i = 0; i < len; i++) {
    wmemmove(p + wcslen(*tr), p + wcslen(*l), wcslen(p + wcslen(*l)) + 1);
    wmemcpy(p, *tr, wcslen(*tr));
    p += wcslen(*tr);
  }
  return txt;
}
""")

# Compile the CFFI library
ffi.compile()

# Initialize the lib object
lib = ffi.lib

# Benchmark the CFFI replacement method
ffi_time = timeit(f'lib.wreplace(lib.new("wchar_t[]", txt), lib.new("wchar_ptr[]", l), lib.new("wchar_ptr[]", tr), len)', number=100)
print("FFI Replacement Time:", ffi_time)

# Benchmark the Python replacement method
python_time = timeit(f'txt.replace(l[0], tr[0]).replace(l[1], tr[1])', number=100)
print("Python Replacement Time:", python_time)

if ffi_time < python_time:
    print("FFI replacement is faster=замена происходит быстрее")
else:
    print("Python replacement is faster=замена происходит быстрее")
после запуска море ошибок, нейросеть подсказала:
Сообщение об ошибке указывает, что компилятору C не удается скомпилировать код C, созданный CFFI. Конкретное сообщение об ошибке предполагает, что в компиляторе отсутствует необходимая библиотека.

Чтобы решить эту проблему, вам необходимо убедиться, что в вашей системе установлены необходимые библиотеки. Это можно сделать, установив пакет Microsoft C++ Build Tools с веб-сайта Microsoft.

Ниже приведены инструкции по установке пакета Microsoft C++ Build Tools:

Перейдите на веб-сайт Microsoft и загрузите установщик Microsoft C++ Build Tools для вашей операционной системы.
Запустите установщик и следуйте инструкциям на экране, чтобы установить пакет.
После завершения установки вы сможете скомпилировать код C, сгенерированный CFFI, без возникновения ошибки CompileError.
установил, не помогло, может перезагрузка нужна?
разбираться буду завтра.........всем добра

Последний раз редактировалось Ципихович Эндрю; 22.12.2023 в 23:04.
Ципихович Эндрю вне форума Ответить с цитированием
Старый 23.12.2023, 01:18   #7
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Цитата:
Сообщение от Ципихович Эндрю Посмотреть сообщение
нейросеть подсказала
Похоже не стоит надеяться на адекватный код от нее.
Цитата:
Сообщение от Ципихович Эндрю Посмотреть сообщение
это как?
Передать сразу список замен. Но по замерам улучшения не наблюдается.
Код:
from cffi import FFI

ffi = FFI()
ffi.cdef("""wchar_t *wreplace(wchar_t *txt, wchar_t *l, wchar_t *tr);
wchar_t *wreplace_few(wchar_t *txt, wchar_t **l, wchar_t **tr, int count);
""")
ffi.set_source("my_module", """#include <stdio.h>

wchar_t *wreplace(wchar_t *txt, wchar_t *l, wchar_t *tr) {
  wchar_t *p = txt;
  while ((p = wcsstr(p, l)) != NULL) {
    wmemmove(p + wcslen(tr), p + wcslen(l), wcslen(p + wcslen(l)) + 1);
    wmemcpy(p, tr, wcslen(tr));
    p += wcslen(tr);
  }
  return txt;
}

wchar_t *wreplace_few(wchar_t *txt, wchar_t **l, wchar_t **tr, int count) {
  for (int i = 0; i < count; i++) {
    wchar_t *p = txt;
    while ((p = wcsstr(p, l[i])) != NULL) {
      wmemmove(p + wcslen(tr[i]), p + wcslen(l[i]), wcslen(p + wcslen(l[i])) + 1);
      wmemcpy(p, tr[i], wcslen(tr[i]));
      p += wcslen(tr[i]);
    }
  }
  return txt;
}
""")

ffi.compile()

from my_module import ffi, lib
import timeit

txt = "Это строка. Это еще одна строка."

l = "строка"
tr = "текст"

print(timeit.timeit('ffi.string(lib.wreplace(ffi.new("wchar_t[]", txt), ffi.new("wchar_t[]", l), ffi.new("wchar_t[]", tr)))', globals = globals(), number = 10000))
print(timeit.timeit('txt.replace(l, tr)', globals = globals(), number = 10000))

l = ["строка", "Это", "еще", "одна"]
tr = ["текст", "То", "не", "один"]

ffi_l = [ffi.new("wchar_t[]", x) for x in l]
ffi_tr = [ffi.new("wchar_t[]", x) for x in tr]
print(ffi.string(lib.wreplace_few(
    ffi.new("wchar_t[]", txt),
    ffi.new("wchar_t *[]", ffi_l),
    ffi.new("wchar_t *[]", ffi_tr),
    ffi.cast("int", len(l))
)))
print(txt.replace(l[0], tr[0]).replace(l[1], tr[1]).replace(l[2], tr[2]).replace(l[3], tr[3]))

print(timeit.timeit('''
ffi_l = [ffi.new("wchar_t[]", x) for x in l]
ffi_tr = [ffi.new("wchar_t[]", x) for x in tr]
ffi.string(lib.wreplace_few(
    ffi.new("wchar_t[]", txt),
    ffi.new("wchar_t *[]", ffi_l),
    ffi.new("wchar_t *[]", ffi_tr),
    ffi.cast("int", len(l))
))''', globals = globals(), number = 10000))
print(timeit.timeit('txt.replace(l[0], tr[0]).replace(l[1], tr[1]).replace(l[2], tr[2]).replace(l[3], tr[3])', globals = globals(), number = 10000))
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )

Последний раз редактировалось BDA; 23.12.2023 в 10:52. Причина: забыл пофиксить код в timeit
BDA на форуме Ответить с цитированием
Старый 23.12.2023, 08:56   #8
Ципихович Эндрю
Старожил
 
Регистрация: 24.01.2011
Сообщений: 3,043
По умолчанию

Цитата:
Сообщение от BDA Посмотреть сообщение
Но по замерам улучшения не наблюдается
понятно, с каждого утюга гутарят, что СИ ракета...........
Ципихович Эндрю вне форума Ответить с цитированием
Старый 23.12.2023, 09:36   #9
p51x
Старожил
 
Регистрация: 15.02.2010
Сообщений: 15,709
По умолчанию

Я вам открою пару секретов:
  1. пайтоновский replace написан не на бейсике
  2. на феррари тоже можно ехать медленно

Может вы хочь чуть начнете вязыках разбираться, а не копировать что-то откуда-то? Начните с выноса вычисления длин из цикла.
p51x вне форума Ответить с цитированием
Старый 23.12.2023, 11:12   #10
BDA
МегаМодератор
СуперМодератор
 
Аватар для BDA
 
Регистрация: 09.11.2010
Сообщений: 7,291
По умолчанию

Цитата:
Сообщение от Ципихович Эндрю Посмотреть сообщение
гутарят, что СИ ракета
Так питон не так уж плох
Вызов с-кода не бесплатен, 80% времени уходит на подготовку данных для вызова:
Код:
from cffi import FFI

ffi = FFI()
ffi.cdef("""wchar_t *wreplace_few(wchar_t *txt, wchar_t **l, wchar_t **tr, int count);""")
ffi.set_source("my_module", """#include <stdio.h>

wchar_t *wreplace_few(wchar_t *txt, wchar_t **l, wchar_t **tr, int count) {
  for (int i = 0; i < count; i++) {
    wchar_t *p = txt;
    while ((p = wcsstr(p, l[i])) != NULL) {
      wmemmove(p + wcslen(tr[i]), p + wcslen(l[i]), wcslen(p + wcslen(l[i])) + 1);
      wmemcpy(p, tr[i], wcslen(tr[i]));
      p += wcslen(tr[i]);
    }
  }
  return txt;
}
""")

ffi.compile()

from my_module import ffi, lib
import timeit

txt = "Это строка. Это еще одна строка."

l = ["строка", "Это", "еще", "одна"]
tr = ["текст", "То", "не", "один"]

ffi_l_items = [ffi.new("wchar_t[]", x) for x in l]
ffi_l = ffi.new("wchar_t *[]", ffi_l_items)
ffi_tr_items = [ffi.new("wchar_t[]", x) for x in tr]
ffi_tr = ffi.new("wchar_t *[]", ffi_tr_items)

print(timeit.timeit('''
ffi_l_items = [ffi.new("wchar_t[]", x) for x in l]
ffi_tr_items = [ffi.new("wchar_t[]", x) for x in tr]
ffi.string(lib.wreplace_few(
    ffi.new("wchar_t[]", txt),
    ffi.new("wchar_t *[]", ffi_l_items),
    ffi.new("wchar_t *[]", ffi_tr_items),
    ffi.cast("int", len(l))
))''', globals = globals(), number = 10000))
print(timeit.timeit('''
ffi.string(lib.wreplace_few(
    ffi.new("wchar_t[]", txt),
    ffi_l,
    ffi_tr,
    ffi.cast("int", len(l))
))''', globals = globals(), number = 10000))
print(timeit.timeit('txt.replace(l[0], tr[0]).replace(l[1], tr[1]).replace(l[2], tr[2]).replace(l[3], tr[3])', globals = globals(), number = 10000))
Пишите язык программирования - это форум программистов, а не экстрасенсов. (<= это подпись )
BDA на форуме Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как в PySimpleGUI добавить код замены ссылки в скрипте Python satfan Python 0 12.12.2021 13:36
[c++] Транспонирование матрицы. Нужно разобраться в коде, напишите пожалуйста что делает каждая строка Enni Общие вопросы C/C++ 6 10.09.2016 17:59