Skip to content

Instantly share code, notes, and snippets.

@mifth
Created July 2, 2026 08:49
Show Gist options
  • Select an option

  • Save mifth/b7c233d3fe7eee5ad9f5140930a8cd16 to your computer and use it in GitHub Desktop.

Select an option

Save mifth/b7c233d3fe7eee5ad9f5140930a8cd16 to your computer and use it in GitHub Desktop.
Anki files generator.
#!/usr/bin/env python3
"""
Generate Anki .apkg files from .txt files
Each line in .txt files should be: English;Italian
"""
import os
import re
from pathlib import Path
import genanki
def sanitize_filename(filename):
"""Convert filename to a valid deck name"""
# Remove .txt extension
name = filename.replace('.txt', '')
# Replace underscores with spaces
name = name.replace('_', ' ')
# Remove 'anki italian' prefix if present
name = re.sub(r'^anki\s+italian\s+', '', name, flags=re.IGNORECASE)
# Capitalize words
name = ' '.join(word.capitalize() for word in name.split())
return name
def create_apkg(txt_file, output_dir):
"""Generate .apkg file from a .txt file"""
try:
txt_path = Path(txt_file)
deck_name = sanitize_filename(txt_path.name)
# Generate a consistent numeric ID based on filename
deck_id = abs(hash(txt_path.name)) % (10 ** 10)
model_id = abs(hash(txt_path.name + '_model')) % (10 ** 10)
font_size = 24
# Create model (card template)
model = genanki.Model(
model_id,
'Italian Vocabulary',
fields=[
{'name': 'Front'},
{'name': 'Back'},
],
templates=[
{
'name': 'Card 1',
'qfmt': f'<div style="text-align: center; font-size: {font_size}px; padding: 20px; margin: 0; line-height: 1.2;">{{{{Front}}}}</div><div style="text-align: center; font-size: {font_size}px; padding: 20px; margin: 0; visibility: hidden;">{{{{Back}}}}</div>',
'afmt': f'<div style="text-align: center; font-size: {font_size}px; padding: 20px; margin: 0; line-height: 1.2;">{{{{Front}}}}</div><hr id=answer style="margin: 20px 0;"><div style="text-align: center; font-size: {font_size}px; padding: 20px; margin: 0;">{{{{Back}}}}</div>',
},
])
# Create deck
deck = genanki.Deck(deck_id, deck_name)
# Parse txt file and add notes
notes = []
with open(txt_file, 'r', encoding='utf-8') as f:
for line in f:
line = line.strip()
if not line or ';' not in line:
continue
parts = line.split(';', 1)
if len(parts) == 2:
front, back = parts
front = front.strip()
back = back.strip()
if front and back:
note = genanki.Note(
model=model,
fields=[front, back]
)
notes.append(note)
# Add all notes to deck
for note in notes:
deck.add_note(note)
# Generate output filename
output_filename = txt_path.stem + '.apkg'
output_path = os.path.join(output_dir, output_filename)
# Package the deck
genanki.Package(deck).write_to_file(output_path)
print(f'✓ Created {output_filename} ({len(notes)} cards)')
except Exception as e:
print(f'✗ Error processing {txt_file}: {e}')
def main():
"""Process all .txt files in the current directory"""
current_dir = Path(__file__).parent
output_dir = current_dir
# Find all .txt files
txt_files = sorted(current_dir.glob('anki_*.txt'))
if not txt_files:
print('No .txt files found matching anki_*.txt pattern')
return
print(f'Found {len(txt_files)} .txt files')
print('Generating .apkg files...\n')
for txt_file in txt_files:
create_apkg(txt_file, output_dir)
print(f'\n✓ All .apkg files generated in {output_dir}')
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment