Это решение работает с механизмом базы данных Access 2010:
Необходимая ссылка:
Microsoft.Office.interop.access.dao
Код:
public void CompactDb(
string sourceFilePath, string destFilePath, string password)
{
var dbEngine = new Microsoft.Office.Interop.Access.Dao.DBEngine();
dbEngine.CompactDatabase(sourceFilePath, destFilePath,
";pwd=" + password, null, ";pwd=" + password);
}
(Исходные файлы и файлы destFilePath не должны быть одинаковыми!) [/ g3]
Параметры метода CompactDatabase (от отражения):
void CompactDatabase(
string SrcName, string DstName,
object DstLocale = Type.Missing,
object Options = Type.Missing,
object SrcLocale = Type.Missing);
Убедитесь, что вы запустили его на той же платформе, что и AccessDatabaseEngine (или Office) (x86 / x64).
Несколько комментариев о вашем коде:
global
переменные пугают меня! что не так с передачей параметров и возвращением состояния? Pandas
, создавая фрейм данных только для того, чтобы использовать его для тупой итерации по строкам, это заставляет его выполнять много ненужной работы csv
(может использоваться с delimiter='|'
) обеспечивает гораздо более тесный интерфейс, если это действительно лучший способ сделать это это может быть лучший вопрос для https://codereview.stackexchange.com/
, просто играющих с производительностью альтернативных способов работы со строками. Из приведенного ниже поясняется, что работа «по строкам» в основном всегда медленная, когда Панды
начинают с создания кадра данных, чтобы проверить это:
import numpy as np
import pandas as pd
df = pd.DataFrame(np.random.randint(1, 1e6, (10_000, 2)))
df[1] = df[1].apply(str)
это занимает 3,65 мс для создать фрейм данных со столбцами int
и str
. затем я попробую подход iterrows
:
tot = 0
for i, row in df.iterrows():
tot += row[0] / 1e5 < len(row[1])
агрегация довольно тупая, я просто хотел что-то, что использует оба столбца. это занимает страшные длинные 903 мс. затем я пытаюсь выполнить итерации вручную:
tot = 0
for i in range(df.shape[0]):
tot += df.loc[i, 0] / 1e5 < len(df.loc[i, 1])
, что сокращает это до 408 мс. затем я пытаюсь apply
:
def fn(row):
return row[0] / 1e5 < len(row[1])
sum(df.apply(fn, axis=1))
, который в основном совпадает с 368 мс. наконец, я нахожу некоторый код, которым Пандас доволен:
sum(df[0] / 1e5 < df[1].apply(len))
, что занимает 4,15 мс. и другой подход, который пришел мне в голову:
tot = 0
for a, b in zip(df[0], df[1]):
tot += a / 1e5 < len(b)
, что занимает 2,78 мс. в то время как другой вариант:
tot = 0
for a, b in zip(df[0] / 1e5, df[1]):
tot += a < len(b)
занимает 2,29 мс.
iterrows
не использует векторизованные операции. Большинство преимуществ использования pandas
исходят от векторизованных и параллельных операций.
Замените for index, row in df_wf.iterrows():
на df_wf.apply(something, axis=1)
, где something
- это функция, которая инкапсулирует необходимую логику из iterrows
и использует numpy
векторизованные операции.
Также, если ваш df
не помещается в памяти так, что вам нужно пакетное чтение, рассмотрите возможность использования dask
или spark
вместо pandas
.
Дополнительное чтение: https://pandas.pydata.org/pandas-docs/stable/enhancingperf.html