Search code examples
python-2.7python-3.xvcf-vcardvobject

Won't read multiple vcards from .vcf file, vobject.readOne(f) only works the first vcard


    #!/usr/bin/env python2.7

    import vobject

    abfile='/foo/bar/directory/file.vcf'

    def test_vobject_dot_readOne():
        with open(abfile) as f:
            vcard = vobject.readOne(f)
            vcard = vobject.readOne(f)

    test_vobject_dot_readOne()

The above code does not work but if we remove one of the two repeated statements it does. I would like to read vcards one by one. Is there a way to do this with vobject.readOne(f)? How can I read vcard n from the file?

The vcf file I'm using is taken from google contacts (exporting as vcard format). Here is the file contents that I have used in the test with only two vcards:

    BEGIN:VCARD 
    VERSION:3.0
    FN:Foo_bar1
    N:;Foo_bar1;;;
    EMAIL;TYPE=INTERNET:foobar1@foo.bar.com
    END:VCARD
    BEGIN:VCARD
    VERSION:3.0
    FN:Foo_bar2 
    N:;Foo_bar2;;;
    EMAIL;TYPE=INTERNET:foobar2@foo.bar.com
    END:VCARD

One can then use the Vcard readings to perform comparisons to avoid duplicates as shown in another question:

To remove vcard contact duplicates, comparing if two vcards are equal in .vcf file does not work with simple == vobject comparison


Solution

  • Well let's hope I understood correctly what you were trying to do.

    Are you trying to do something like this?

    #!/usr/bin/env python2.7
    
    import vobject
    
    test_vcard_information = r"""BEGIN:VCARD
    VERSION:3.0
    FN:Foo_bar1
    N:;Foo_bar1;
    EMAIL;TYPE=INTERNET:foobar1@foo.bar.com
    END:VCARD
    BEGIN:VCARD
    VERSION:3.0
    FN:Foo_bar2
    N:;Foo_bar2;
    EMAIL;TYPE=INTERNET:foobar2@foo.bar.com
    END:VCARD
    """
    
    for vcard in vobject.readComponents(test_vcard_information):
        print vcard.fn.value
    

    Or if you have the information in a file:

    #!/usr/bin/env python2.7
    
    import vobject
    
    test_filename = r'/path/to/Test_addressbook.vcf'
    
    with open(test_filename) as source_file:
        for vcard in vobject.readComponents(source_file):
           print vcard.fn.value
    

    You would probably use .readOne() with a calendar file (.ics) since it would be composed of a single root object like in this example:

    #!/usr/bin/env python2.7
    
    import vobject
    
    test_calendar_information = r"""BEGIN:VCALENDAR
    PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
    VERSION:2.0
    BEGIN:VTIMEZONE
    TZID:America/Toronto
    BEGIN:DAYLIGHT
    TZOFFSETFROM:-0500
    TZOFFSETTO:-0400
    TZNAME:EDT
    DTSTART:19700308T020000
    RRULE:FREQ=YEARLY;BYDAY=2SU;BYMONTH=3
    END:DAYLIGHT
    BEGIN:STANDARD
    TZOFFSETFROM:-0400
    TZOFFSETTO:-0500
    TZNAME:EST
    DTSTART:19701101T020000
    RRULE:FREQ=YEARLY;BYDAY=1SU;BYMONTH=11
    END:STANDARD
    END:VTIMEZONE
    BEGIN:VEVENT
    CREATED:20170104T022518Z
    LAST-MODIFIED:20170104T022643Z
    DTSTAMP:20170104T022643Z
    UID:3fab09d6-59bb-430b-8b21-56c9636871e2
    SUMMARY:Write a chapter
    CATEGORIES:Projects
    DTSTART;TZID=America/Toronto:20170105T140000
    DTEND;TZID=America/Toronto:20170105T150000
    TRANSP:OPAQUE
    X-MOZ-GENERATION:2
    LOCATION:At home
    DESCRIPTION:One day I will be a great writer but I have to start somewhere...
    SEQUENCE:1
    END:VEVENT
    BEGIN:VEVENT
    CREATED:20170104T022346Z
    LAST-MODIFIED:20170104T022654Z
    DTSTAMP:20170104T022654Z
    UID:b304f46a-f533-4aa4-8ee1-3b59649dedfa
    SUMMARY:See a movie
    CATEGORIES:Entertainment
    DTSTART;TZID=America/Toronto:20170103T110000
    DTEND;TZID=America/Toronto:20170103T140000
    TRANSP:OPAQUE
    X-MOZ-GENERATION:4
    LOCATION:Somewhere over the rainbow
    DESCRIPTION:The Wizard of Oz is movie I haven't seen in a long time.\n\nWe
      should schedule a time to see it
    SEQUENCE:1
    END:VEVENT
    END:VCALENDAR"""
    
    vcalendar = vobject.readOne(test_calendar_information)
    for vevent in vcalendar.vevent_list:
        print vevent.summary.value
    

    Or if it is in a file:

    #!/usr/bin/env python2.7
    
    import vobject
    
    test_filename = r'/path/to/Test_Calendar.ics'
    
    with open(test_filename) as source_file:
        vcalendar = vobject.readOne(source_file)
        for vevent in vcalendar.vevent_list:
            print vevent.summary.value