<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def create_session(self, location=None, media_mode=MediaModes.relayed, archive_mode=ArchiveModes.manual):
 """ Creates a new OpenTok session and returns the session ID, which uniquely identifies the session. For example, when using the OpenTok JavaScript library, use the session ID when calling the OT.initSession() method (to initialize an OpenTok session). OpenTok sessions do not expire. However, authentication tokens do expire (see the generateToken() method). Also note that sessions cannot explicitly be destroyed. A session ID string can be up to 255 characters long. Calling this method results in an OpenTokException in the event of an error. Check the error message for details. You can also create a session using the OpenTok `REST API <https://tokbox.com/opentok/api/#session_id_production>`_ or `the OpenTok dashboard <https://dashboard.tokbox.com/projects>`_. :param String media_mode: Determines whether the session will transmit streams using the OpenTok Media Router (MediaMode.routed) or not (MediaMode.relayed). By default, the setting is MediaMode.relayed. With the media_mode property set to MediaMode.relayed, the session will attempt to transmit streams directly between clients. If clients cannot connect due to firewall restrictions, the session uses the OpenTok TURN server to relay audio-video streams. The `OpenTok Media Router <https://tokbox.com/opentok/tutorials/create-session/#media-mode>`_ provides the following benefits: * The OpenTok Media Router can decrease bandwidth usage in multiparty sessions. (When the mediaMode property is set to MediaMode.relayed, each client must send a separate audio-video stream to each client subscribing to it.) * The OpenTok Media Router can improve the quality of the user experience through audio fallback and video recovery (see https://tokbox.com/platform/fallback). With these features, if a client's connectivity degrades to a degree that it does not support video for a stream it's subscribing to, the video is dropped on that client (without affecting other clients), and the client receives audio only. If the client's connectivity improves, the video returns. * The OpenTok Media Router supports the archiving feature, which lets you record, save, and retrieve OpenTok sessions (see http://tokbox.com/platform/archiving). :param String archive_mode: Whether the session is automatically archived (ArchiveModes.always) or not (ArchiveModes.manual). By default, the setting is ArchiveModes.manual, and you must call the start_archive() method of the OpenTok object to start archiving. To archive the session (either automatically or not), you must set the media_mode parameter to MediaModes.routed. :param String location: An IP address that the OpenTok servers will use to situate the session in its global network. If you do not set a location hint, the OpenTok servers will be based on the first client connecting to the session. :rtype: The Session object. The session_id property of the object is the session ID. """


        # build options
        options = {}
        if not isinstance(media_mode, MediaModes):
            raise OpenTokException(u('Cannot create session, {0} is not a valid media mode').format(media_mode))
        if not isinstance(archive_mode, ArchiveModes):
            raise OpenTokException(u('Cannot create session, {0} is not a valid archive mode').format(archive_mode))
        if archive_mode == ArchiveModes.always and media_mode != MediaModes.routed:
            raise OpenTokException(u('A session with always archive mode must also have the routed media mode.'))
        options[u('p2p.preference')] = media_mode.value
        options[u('archiveMode')] = archive_mode.value
        if location:
            # validate IP address
            try:
                inet_aton(location)
            except:
                raise OpenTokException(u('Cannot create session. Location must be either None or a valid IPv4 address {0}').format(location))
            options[u('location')] = location

        try:
            response = requests.post(self.endpoints.session_url(), data=options, headers=self.headers(), proxies=self.proxies, timeout=self.timeout)
            response.encoding = 'utf-8'

            if response.status_code == 403:
                raise AuthError('Failed to create session, invalid credentials')
            if not response.content:
                raise RequestError()
            dom = xmldom.parseString(response.content)
        except Exception as e:
            raise RequestError('Failed to create session: %s' % str(e))

        try:
            error = dom.getElementsByTagName('error')
            if error:
                error = error[0]
                raise AuthError('Failed to create session (code=%s): %s' % (error.attributes['code'].value, error.firstChild.attributes['message'].value))

            session_id = dom.getElementsByTagName('session_id')[0].childNodes[0].nodeValue
            return Session(self, session_id, location=location, media_mode=media_mode, archive_mode=archive_mode)
        except Exception as e:
            raise OpenTokException('Failed to generate session: %s' % str(e))