9

I want to change the port in given url.

OLD=http://test:7000/vcc3 NEW=http://test:7777/vcc3

I tried below code code, I am able to change the URL but not able to change the port.

>>> from urlparse import urlparse
>>> aaa = urlparse('http://test:7000/vcc3')
>>> aaa.hostname
test
>>> aaa.port
7000
>>>aaa._replace(netloc=aaa.netloc.replace(aaa.hostname,"newurl")).geturl()
'http://newurl:7000/vcc3'
>>>aaa._replace(netloc=aaa.netloc.replace(aaa.port,"7777")).geturl()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: expected a character buffer object
0

3 Answers 3

11

It's not a particularly good error message. It's complaining because you're passing ParseResult.port, an int, to the string's replace method which expects a str. Just stringify port before you pass it in:

aaa._replace(netloc=aaa.netloc.replace(str(aaa.port), "7777"))

I'm astonished that there isn't a simple way to set the port using the urlparse library. It feels like an oversight. Ideally you'd be able to say something like parseresult._replace(port=7777), but alas, that doesn't work.

Sign up to request clarification or add additional context in comments.

2 Comments

Are we suppose to use _replace method directly ? Rule of thumb is, you should not invoke private methods on objects directly.
@AashishP Good question. namedtuple flouts convention somewhat; _replace is not intended to be a private method. It's named with an underscore to minimise the likelihood of name-conflicts with a field in the namedtuple. (Scroll up from the linked documentation and you'll find the sentence "To prevent conflicts with field names, the method and attribute names start with an underscore.")
8

The details of the port are stored in netloc, so you can simply do:

>>> a = urlparse('http://test:7000/vcc3')
>>> a._replace(netloc='newurl:7777').geturl()
'http://newurl:7777/vcc3'
>>> a._replace(netloc=a.hostname+':7777').geturl()  # Keep the same host
'http://test:7777/vcc3'

2 Comments

Much cleaner than the currently accepted answer, which I just edited to have a bit of dancing around in order to guard against edge cases
Unfortunately, this can still be missing the username and password in the original netloc. It's amazing how complicated urllib made this seemingly simple task of changing a port...
3

The problem is that the ParseResult 's 'port' member is protected and you can't change the attribute -don't event try to use private _replace() method. Solution is here:

from urllib.parse import urlparse, ParseResult

old = urlparse('http://test:7000/vcc3')
new = ParseResult(scheme=a.scheme, netloc="{}:{}".format(old.hostname, 7777),
                  path=old.path, params=old.params, query=old.query, fragment=old.fragment)
new_url = new.geturl()

The second idea is to convert ParseResult to list->change it later on like here:

Changing hostname in a url

BTW 'urlparse' library is not flexible in that area!

2 Comments

I guess you meant scheme=old.scheme
The ._replace() method isn't private. See Benjamin Hodgson's comment in another answer on this page.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.