Random IP Address Generator












35














randip.py



I know there are probably better, easier ways to do this.

It was just a bit of a learning exercise for the sake of familiarising myself with Python.



It takes a single argument (positional parameter):

Either a 4 (IPv4) or a 6 (IPv6).





Usage:




./randip.py 4
61.104.170.242


./randip.py 6
4bfc:391d:3ec8:68ef:0ec8:529b:166d:2ece




Code:



#!/usr/bin/env python3

from sys import argv

from random import randint, choice
from string import hexdigits

def random_ip(v):

if v == 4:
octets =
for x in range(4):
octets.append(str(randint(0,255)))
return '.'.join(octets)

elif v == 6:
octets =
for x in range(8):
octet =
for x in range(4):
octet.append(str(choice(hexdigits.lower())))
octets.append(''.join(octet))
return ':'.join(octets)

else:
return

def main():
print(random_ip(int(argv[1])))

if __name__ == '__main__':
main()









share|improve this question





























    35














    randip.py



    I know there are probably better, easier ways to do this.

    It was just a bit of a learning exercise for the sake of familiarising myself with Python.



    It takes a single argument (positional parameter):

    Either a 4 (IPv4) or a 6 (IPv6).





    Usage:




    ./randip.py 4
    61.104.170.242


    ./randip.py 6
    4bfc:391d:3ec8:68ef:0ec8:529b:166d:2ece




    Code:



    #!/usr/bin/env python3

    from sys import argv

    from random import randint, choice
    from string import hexdigits

    def random_ip(v):

    if v == 4:
    octets =
    for x in range(4):
    octets.append(str(randint(0,255)))
    return '.'.join(octets)

    elif v == 6:
    octets =
    for x in range(8):
    octet =
    for x in range(4):
    octet.append(str(choice(hexdigits.lower())))
    octets.append(''.join(octet))
    return ':'.join(octets)

    else:
    return

    def main():
    print(random_ip(int(argv[1])))

    if __name__ == '__main__':
    main()









    share|improve this question



























      35












      35








      35


      9





      randip.py



      I know there are probably better, easier ways to do this.

      It was just a bit of a learning exercise for the sake of familiarising myself with Python.



      It takes a single argument (positional parameter):

      Either a 4 (IPv4) or a 6 (IPv6).





      Usage:




      ./randip.py 4
      61.104.170.242


      ./randip.py 6
      4bfc:391d:3ec8:68ef:0ec8:529b:166d:2ece




      Code:



      #!/usr/bin/env python3

      from sys import argv

      from random import randint, choice
      from string import hexdigits

      def random_ip(v):

      if v == 4:
      octets =
      for x in range(4):
      octets.append(str(randint(0,255)))
      return '.'.join(octets)

      elif v == 6:
      octets =
      for x in range(8):
      octet =
      for x in range(4):
      octet.append(str(choice(hexdigits.lower())))
      octets.append(''.join(octet))
      return ':'.join(octets)

      else:
      return

      def main():
      print(random_ip(int(argv[1])))

      if __name__ == '__main__':
      main()









      share|improve this question















      randip.py



      I know there are probably better, easier ways to do this.

      It was just a bit of a learning exercise for the sake of familiarising myself with Python.



      It takes a single argument (positional parameter):

      Either a 4 (IPv4) or a 6 (IPv6).





      Usage:




      ./randip.py 4
      61.104.170.242


      ./randip.py 6
      4bfc:391d:3ec8:68ef:0ec8:529b:166d:2ece




      Code:



      #!/usr/bin/env python3

      from sys import argv

      from random import randint, choice
      from string import hexdigits

      def random_ip(v):

      if v == 4:
      octets =
      for x in range(4):
      octets.append(str(randint(0,255)))
      return '.'.join(octets)

      elif v == 6:
      octets =
      for x in range(8):
      octet =
      for x in range(4):
      octet.append(str(choice(hexdigits.lower())))
      octets.append(''.join(octet))
      return ':'.join(octets)

      else:
      return

      def main():
      print(random_ip(int(argv[1])))

      if __name__ == '__main__':
      main()






      python python-3.x random reinventing-the-wheel ip-address






      share|improve this question















      share|improve this question













      share|improve this question




      share|improve this question








      edited 1 hour ago

























      asked Jul 26 at 12:05









      tjt263

      29637




      29637






















          6 Answers
          6






          active

          oldest

          votes


















          51














          Python is often described as a "batteries included" kind of language, and this is no exception.



          There's a module just for IP address manipulation and another module to generate random numbers. Put together, they do exactly what you want, in a way that's slightly more readable (IMO).



          For this example, I'll assume that the variable v contains either 4 or 6.



          from random import getrandbits
          from ipaddress import IPv4Address, IPv6Address

          if v == 4:
          bits = getrandbits(32) # generates an integer with 32 random bits
          addr = IPv4Address(bits) # instances an IPv4Address object from those bits
          addr_str = str(addr) # get the IPv4Address object's string representation
          elif v == 6:
          bits = getrandbits(128) # generates an integer with 128 random bits
          addr = IPv6Address(bits) # instances an IPv6Address object from those bits
          # .compressed contains the short version of the IPv6 address
          # str(addr) always returns the short address
          # .exploded is the opposite of this, always returning the full address with all-zero groups and so on
          addr_str = addr.compressed

          print(addr_str)


          Here, addr_str will hold a fully random IPv4 or IPv6 address.



          You can even generate random addresses from a subnet like this:



          from random import getrandbits
          from ipaddress import IPv4Network, IPv4Address

          # network containing all addresses from 10.0.0.0 to 10.0.0.255
          subnet = IPv4Network("10.0.0.0/24")

          # subnet.max_prefixlen contains 32 for IPv4 subnets and 128 for IPv6 subnets
          # subnet.prefixlen is 24 in this case, so we'll generate only 8 random bits
          bits = getrandbits(subnet.max_prefixlen - subnet.prefixlen)

          # here, we combine the subnet and the random bits
          # to get an IP address from the previously specified subnet
          addr = IPv4Address(subnet.network_address + bits)
          addr_str = str(addr)

          print(addr_str)


          Here, addr_str will always contain IP addresses like 10.0.0.184, 10.0.0.42 and so on. It works the same way with IPv6 addresses, except in that case you'd have to import IPv6Network and IPv6Address instead.






          share|improve this answer



















          • 7




            Nice solution - did you consider pushing addr_str = addr.compressed to after the conditional?
            – cmh
            Jul 26 at 15:07






          • 4




            @tjt263 Yeah, I'd say this might have less educational value than your approach, even though it is a much better way to just generate a random IP address if that's what you really want.
            – David Z
            Jul 26 at 17:46






          • 5




            In CodeReview users aren't trying to do something as efficiently as possible with builtins, but rather get the form of their approach right. Telling someone who's writing an IP generator from scratch to just import it doesn't really serve the community.
            – user1717828
            Jul 26 at 20:42






          • 7




            Before posting it, I considered prefacing my answer with something like "This isn't a proper answer for Code Review, but...", but I didn't think it'd blow up like this. I intended it to be a helpful resource for future people finding this via Google, because just a few months ago, I was in the exact same situation as OP: wanting to write an IP randomizer, not knowing Python could do it for me. I've added a few comments to my examples, hopefully they'll make it more obvious how the code works.
            – Peter W.
            Jul 27 at 6:58






          • 2




            @user1717828 That's not true. If you are open to feedback on CRSE, you are inherently open to alternative solutions to the problem. If you purposefully choose to reinvent the wheel (as a personal challenge or otherwise), there's the reinventing-the-wheel tag.
            – Daniel
            Jul 27 at 23:12



















          25














          Here are a few ideas about your code.



          Check for command line arguments



          The code fails with an exception if it's invoked with no command line arguments because it attempts to use argv[1] and there isn't any. I'd suggest that it would be nice to print a "usage" message if the user enters either an invalid or no argument.



          Use a list comprehension



          List comprehensions are extremely useful and very Pythonic. It's really good to become proficient with them. Here's how to use one to generate a random IPv4 address:



          '.'.join([str(randint(0,255)) for x in range(4)])


          And an IPv6 address is a little trickier because we need hex digits.



          ':'.join([hex(randint(2**16,2**17))[-4:] for x in range(8)])


          That works because randint generates a number in the range 0x10000 to 0x20000 and we then pick off the last four hex digits.






          share|improve this answer





















          • Thanks. That last part's a bit clever. I had a similar idea, but wasn't able to pull it off. The list comprehensions are a nice touch too, just a bit trickier to articulate.
            – tjt263
            Jul 26 at 13:37






          • 3




            you can use 0x10000 and 0x20000 instead of 2**16 and 2**17 for better readability.
            – Mathias Ettinger
            Jul 26 at 13:40






          • 2




            It might be worth mentioning that you don't need the list comprehension to really be a list. It could be a generator instead.
            – David Z
            Jul 26 at 17:48










          • For IPv6, leading zeroes in a group can be omitted, so you don't need that trick, and just do ':'.join(hex(randrange(0x10000))[2:] for x in range(8))
            – Robin
            Jul 27 at 12:38












          • @Robin: it's true, but I like to make it appear consistent. Personally, I prefer PeterW. 's answer. Very elegant!
            – Edward
            Jul 27 at 12:40



















          19














          For someone not familiar with Python, you have picked pretty good habits. Not everyone uses functions or the if __name__ == '__main__' guard first try.



          That being said, I think it would make more sense to provide 2 functions instead of a single one: random_ipv4 and random_ipv6.



          You could also feed generator expressions to join. They are both faster to process than + for + append and easier to read:



          def random_ipv4():
          return '.'.join(str(randint(0,255)) for _ in range(4))


          def random_ipv6():
          return ':'.join(
          ''.join(choice(hexdigits).lower() for _ in range(4))
          for _ in range(8)
          )


          The only thing left being to properly validate that the input is either 4 or 6:



          if __name__ == '__main__':
          if len(sys.argv) < 2:
          sys.exit('Usage: python random_ip.py VERSION')

          version = sys.argv[1]
          if version == '4':
          print(random_ipv4())
          elif version == '6':
          print(random_ipv6())
          else:
          sys.exit('VERSION should be 4 or 6, not {}'.format(version))





          share|improve this answer





















          • CMIIW, but aren't list comprehension a bit faster than generator comprehension when memory is not an issue?
            – Ludisposed
            Jul 26 at 14:01










          • @Ludisposed Found old timings at bytes.com/topic/python/answers/… But for join it shouldn't matter much as the current implementation convert the input to a list right away.
            – Mathias Ettinger
            Jul 26 at 14:49










          • @Ludisposed My own testing indicates 5.792979179001122 seconds for 1 million calls to random_ipv4 using a generator expression and 5.526552320003248 using a list-comprehension. Nothing really conclusive to prefer one over the other. And since we aren't to re-use the result, a generator expression is a good indication of that.
            – Mathias Ettinger
            Jul 26 at 15:01








          • 1




            Yes it shouldn't matter much and is dependent on the data. I agree with your reasoning for choosing a generator.
            – Ludisposed
            Jul 26 at 15:11



















          14














          Check for invalid outputs, and regenerate them.



          It's possible that you'll produce an output that's reserved for a particular purpose, such as loopback (127.0.0.1 or ::1) or broadcast (255.255.255.255, ff02::1, ff02::2). Build in knowledge of such addresses, and if you find you've produced one, then replace it. You can do that recursively:



          def make_address(v):
          address = random_ip(v)
          if is_reserved(address):
          return make_address(v)
          return address





          share|improve this answer

















          • 2




            There is no need for this to be recursive. It might as well be a while is_reserved(address): loop. But then again, if the chance to generate a valid IP is only a per mille (so you are in danger of regularly hitting the stack size limit), you are probably doing something wrong...
            – Graipher
            Jul 26 at 15:20






          • 1




            Yes, I was just showing one way. Python's only an occasional language for me, and I couldn't remember whether it guarantees tail-call elimination...
            – Toby Speight
            Jul 26 at 16:13










          • Maybe you want extra options to create IPv6 addresses formed from mapping IPv4 addresses and from hardware MAC addresses, then.
            – Toby Speight
            Jul 26 at 16:59








          • 1




            @TobySpeight It doesn't, but there is a way to guarantee it manually, by using a decorator: stackoverflow.com/q/27417874/2415524
            – mbomb007
            Jul 27 at 21:52



















          12














          Validate the input: At present, your program




          • aborts with IndexError if called without arguments,

          • aborts with ValueError if called with a non-integer argument,

          • prints None if called with an integer argument that is not 4
            or 6.


          Missing or invalid arguments should print a helpful error message.
          Most Unix command-line tools print the message to the standard error
          and terminate with a non-zero exit status in the case of a failure.



          It would be easier to compare the given argument against the
          strings "4" and "6" instead of converting it to an integer
          (which can fail).





          Use list comprehension instead of appending to an array in a loop.
          Use _ as iterator variable if the concrete value is not needed.



          As an example, the "IPv4" case can be implemented as



          if v == 4:
          return '.'.join(str(randint(0,255)) for _ in range(4))





          share|improve this answer





















          • Why _? Is that a thing people do? I've never seen it before.
            – tjt263
            Jul 26 at 17:45






          • 2




            @tjt263: It is just by convention used as a “throw-away variable,” see for example stackoverflow.com/q/5893163/1187415
            – Martin R
            Jul 26 at 18:27



















          7














          Since you already got a couple of answers telling you to validate your inputs, here is a way how to do it using the argparse module:



          import argparse

          if __name__ == "__main__":
          parser = argparse.ArgumentParser()
          parser.add_argument('-v',
          type=int,
          choices=(4, 6),
          default=4,
          help="Whether to generate a random IPv4 or IPv6 address. Default: IPv4.")
          args = parser.parse_args()
          print(random_ip(args.v))


          You can then use it on the command line like this:



          ./randip
          ./randip -v 4
          ./randip -v4
          ./randip -v 6


          If you do anything else, a helpful usage message is printed:



          usage: [-h] [-v {4,6}]

          optional arguments:
          -h, --help show this help message and exit
          -v {4,6} Whether to generate a random IPv4 or IPv6 address. Default:
          IPv4.





          share|improve this answer























            Your Answer





            StackExchange.ifUsing("editor", function () {
            return StackExchange.using("mathjaxEditing", function () {
            StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix) {
            StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
            });
            });
            }, "mathjax-editing");

            StackExchange.ifUsing("editor", function () {
            StackExchange.using("externalEditor", function () {
            StackExchange.using("snippets", function () {
            StackExchange.snippets.init();
            });
            });
            }, "code-snippets");

            StackExchange.ready(function() {
            var channelOptions = {
            tags: "".split(" "),
            id: "196"
            };
            initTagRenderer("".split(" "), "".split(" "), channelOptions);

            StackExchange.using("externalEditor", function() {
            // Have to fire editor after snippets, if snippets enabled
            if (StackExchange.settings.snippets.snippetsEnabled) {
            StackExchange.using("snippets", function() {
            createEditor();
            });
            }
            else {
            createEditor();
            }
            });

            function createEditor() {
            StackExchange.prepareEditor({
            heartbeatType: 'answer',
            autoActivateHeartbeat: false,
            convertImagesToLinks: false,
            noModals: true,
            showLowRepImageUploadWarning: true,
            reputationToPostImages: null,
            bindNavPrevention: true,
            postfix: "",
            imageUploader: {
            brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
            contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
            allowUrls: true
            },
            onDemand: true,
            discardSelector: ".discard-answer"
            ,immediatelyShowMarkdownHelp:true
            });


            }
            });














            draft saved

            draft discarded


















            StackExchange.ready(
            function () {
            StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200337%2frandom-ip-address-generator%23new-answer', 'question_page');
            }
            );

            Post as a guest















            Required, but never shown

























            6 Answers
            6






            active

            oldest

            votes








            6 Answers
            6






            active

            oldest

            votes









            active

            oldest

            votes






            active

            oldest

            votes









            51














            Python is often described as a "batteries included" kind of language, and this is no exception.



            There's a module just for IP address manipulation and another module to generate random numbers. Put together, they do exactly what you want, in a way that's slightly more readable (IMO).



            For this example, I'll assume that the variable v contains either 4 or 6.



            from random import getrandbits
            from ipaddress import IPv4Address, IPv6Address

            if v == 4:
            bits = getrandbits(32) # generates an integer with 32 random bits
            addr = IPv4Address(bits) # instances an IPv4Address object from those bits
            addr_str = str(addr) # get the IPv4Address object's string representation
            elif v == 6:
            bits = getrandbits(128) # generates an integer with 128 random bits
            addr = IPv6Address(bits) # instances an IPv6Address object from those bits
            # .compressed contains the short version of the IPv6 address
            # str(addr) always returns the short address
            # .exploded is the opposite of this, always returning the full address with all-zero groups and so on
            addr_str = addr.compressed

            print(addr_str)


            Here, addr_str will hold a fully random IPv4 or IPv6 address.



            You can even generate random addresses from a subnet like this:



            from random import getrandbits
            from ipaddress import IPv4Network, IPv4Address

            # network containing all addresses from 10.0.0.0 to 10.0.0.255
            subnet = IPv4Network("10.0.0.0/24")

            # subnet.max_prefixlen contains 32 for IPv4 subnets and 128 for IPv6 subnets
            # subnet.prefixlen is 24 in this case, so we'll generate only 8 random bits
            bits = getrandbits(subnet.max_prefixlen - subnet.prefixlen)

            # here, we combine the subnet and the random bits
            # to get an IP address from the previously specified subnet
            addr = IPv4Address(subnet.network_address + bits)
            addr_str = str(addr)

            print(addr_str)


            Here, addr_str will always contain IP addresses like 10.0.0.184, 10.0.0.42 and so on. It works the same way with IPv6 addresses, except in that case you'd have to import IPv6Network and IPv6Address instead.






            share|improve this answer



















            • 7




              Nice solution - did you consider pushing addr_str = addr.compressed to after the conditional?
              – cmh
              Jul 26 at 15:07






            • 4




              @tjt263 Yeah, I'd say this might have less educational value than your approach, even though it is a much better way to just generate a random IP address if that's what you really want.
              – David Z
              Jul 26 at 17:46






            • 5




              In CodeReview users aren't trying to do something as efficiently as possible with builtins, but rather get the form of their approach right. Telling someone who's writing an IP generator from scratch to just import it doesn't really serve the community.
              – user1717828
              Jul 26 at 20:42






            • 7




              Before posting it, I considered prefacing my answer with something like "This isn't a proper answer for Code Review, but...", but I didn't think it'd blow up like this. I intended it to be a helpful resource for future people finding this via Google, because just a few months ago, I was in the exact same situation as OP: wanting to write an IP randomizer, not knowing Python could do it for me. I've added a few comments to my examples, hopefully they'll make it more obvious how the code works.
              – Peter W.
              Jul 27 at 6:58






            • 2




              @user1717828 That's not true. If you are open to feedback on CRSE, you are inherently open to alternative solutions to the problem. If you purposefully choose to reinvent the wheel (as a personal challenge or otherwise), there's the reinventing-the-wheel tag.
              – Daniel
              Jul 27 at 23:12
















            51














            Python is often described as a "batteries included" kind of language, and this is no exception.



            There's a module just for IP address manipulation and another module to generate random numbers. Put together, they do exactly what you want, in a way that's slightly more readable (IMO).



            For this example, I'll assume that the variable v contains either 4 or 6.



            from random import getrandbits
            from ipaddress import IPv4Address, IPv6Address

            if v == 4:
            bits = getrandbits(32) # generates an integer with 32 random bits
            addr = IPv4Address(bits) # instances an IPv4Address object from those bits
            addr_str = str(addr) # get the IPv4Address object's string representation
            elif v == 6:
            bits = getrandbits(128) # generates an integer with 128 random bits
            addr = IPv6Address(bits) # instances an IPv6Address object from those bits
            # .compressed contains the short version of the IPv6 address
            # str(addr) always returns the short address
            # .exploded is the opposite of this, always returning the full address with all-zero groups and so on
            addr_str = addr.compressed

            print(addr_str)


            Here, addr_str will hold a fully random IPv4 or IPv6 address.



            You can even generate random addresses from a subnet like this:



            from random import getrandbits
            from ipaddress import IPv4Network, IPv4Address

            # network containing all addresses from 10.0.0.0 to 10.0.0.255
            subnet = IPv4Network("10.0.0.0/24")

            # subnet.max_prefixlen contains 32 for IPv4 subnets and 128 for IPv6 subnets
            # subnet.prefixlen is 24 in this case, so we'll generate only 8 random bits
            bits = getrandbits(subnet.max_prefixlen - subnet.prefixlen)

            # here, we combine the subnet and the random bits
            # to get an IP address from the previously specified subnet
            addr = IPv4Address(subnet.network_address + bits)
            addr_str = str(addr)

            print(addr_str)


            Here, addr_str will always contain IP addresses like 10.0.0.184, 10.0.0.42 and so on. It works the same way with IPv6 addresses, except in that case you'd have to import IPv6Network and IPv6Address instead.






            share|improve this answer



















            • 7




              Nice solution - did you consider pushing addr_str = addr.compressed to after the conditional?
              – cmh
              Jul 26 at 15:07






            • 4




              @tjt263 Yeah, I'd say this might have less educational value than your approach, even though it is a much better way to just generate a random IP address if that's what you really want.
              – David Z
              Jul 26 at 17:46






            • 5




              In CodeReview users aren't trying to do something as efficiently as possible with builtins, but rather get the form of their approach right. Telling someone who's writing an IP generator from scratch to just import it doesn't really serve the community.
              – user1717828
              Jul 26 at 20:42






            • 7




              Before posting it, I considered prefacing my answer with something like "This isn't a proper answer for Code Review, but...", but I didn't think it'd blow up like this. I intended it to be a helpful resource for future people finding this via Google, because just a few months ago, I was in the exact same situation as OP: wanting to write an IP randomizer, not knowing Python could do it for me. I've added a few comments to my examples, hopefully they'll make it more obvious how the code works.
              – Peter W.
              Jul 27 at 6:58






            • 2




              @user1717828 That's not true. If you are open to feedback on CRSE, you are inherently open to alternative solutions to the problem. If you purposefully choose to reinvent the wheel (as a personal challenge or otherwise), there's the reinventing-the-wheel tag.
              – Daniel
              Jul 27 at 23:12














            51












            51








            51






            Python is often described as a "batteries included" kind of language, and this is no exception.



            There's a module just for IP address manipulation and another module to generate random numbers. Put together, they do exactly what you want, in a way that's slightly more readable (IMO).



            For this example, I'll assume that the variable v contains either 4 or 6.



            from random import getrandbits
            from ipaddress import IPv4Address, IPv6Address

            if v == 4:
            bits = getrandbits(32) # generates an integer with 32 random bits
            addr = IPv4Address(bits) # instances an IPv4Address object from those bits
            addr_str = str(addr) # get the IPv4Address object's string representation
            elif v == 6:
            bits = getrandbits(128) # generates an integer with 128 random bits
            addr = IPv6Address(bits) # instances an IPv6Address object from those bits
            # .compressed contains the short version of the IPv6 address
            # str(addr) always returns the short address
            # .exploded is the opposite of this, always returning the full address with all-zero groups and so on
            addr_str = addr.compressed

            print(addr_str)


            Here, addr_str will hold a fully random IPv4 or IPv6 address.



            You can even generate random addresses from a subnet like this:



            from random import getrandbits
            from ipaddress import IPv4Network, IPv4Address

            # network containing all addresses from 10.0.0.0 to 10.0.0.255
            subnet = IPv4Network("10.0.0.0/24")

            # subnet.max_prefixlen contains 32 for IPv4 subnets and 128 for IPv6 subnets
            # subnet.prefixlen is 24 in this case, so we'll generate only 8 random bits
            bits = getrandbits(subnet.max_prefixlen - subnet.prefixlen)

            # here, we combine the subnet and the random bits
            # to get an IP address from the previously specified subnet
            addr = IPv4Address(subnet.network_address + bits)
            addr_str = str(addr)

            print(addr_str)


            Here, addr_str will always contain IP addresses like 10.0.0.184, 10.0.0.42 and so on. It works the same way with IPv6 addresses, except in that case you'd have to import IPv6Network and IPv6Address instead.






            share|improve this answer














            Python is often described as a "batteries included" kind of language, and this is no exception.



            There's a module just for IP address manipulation and another module to generate random numbers. Put together, they do exactly what you want, in a way that's slightly more readable (IMO).



            For this example, I'll assume that the variable v contains either 4 or 6.



            from random import getrandbits
            from ipaddress import IPv4Address, IPv6Address

            if v == 4:
            bits = getrandbits(32) # generates an integer with 32 random bits
            addr = IPv4Address(bits) # instances an IPv4Address object from those bits
            addr_str = str(addr) # get the IPv4Address object's string representation
            elif v == 6:
            bits = getrandbits(128) # generates an integer with 128 random bits
            addr = IPv6Address(bits) # instances an IPv6Address object from those bits
            # .compressed contains the short version of the IPv6 address
            # str(addr) always returns the short address
            # .exploded is the opposite of this, always returning the full address with all-zero groups and so on
            addr_str = addr.compressed

            print(addr_str)


            Here, addr_str will hold a fully random IPv4 or IPv6 address.



            You can even generate random addresses from a subnet like this:



            from random import getrandbits
            from ipaddress import IPv4Network, IPv4Address

            # network containing all addresses from 10.0.0.0 to 10.0.0.255
            subnet = IPv4Network("10.0.0.0/24")

            # subnet.max_prefixlen contains 32 for IPv4 subnets and 128 for IPv6 subnets
            # subnet.prefixlen is 24 in this case, so we'll generate only 8 random bits
            bits = getrandbits(subnet.max_prefixlen - subnet.prefixlen)

            # here, we combine the subnet and the random bits
            # to get an IP address from the previously specified subnet
            addr = IPv4Address(subnet.network_address + bits)
            addr_str = str(addr)

            print(addr_str)


            Here, addr_str will always contain IP addresses like 10.0.0.184, 10.0.0.42 and so on. It works the same way with IPv6 addresses, except in that case you'd have to import IPv6Network and IPv6Address instead.







            share|improve this answer














            share|improve this answer



            share|improve this answer








            edited Jul 27 at 7:10

























            answered Jul 26 at 13:25









            Peter W.

            57925




            57925








            • 7




              Nice solution - did you consider pushing addr_str = addr.compressed to after the conditional?
              – cmh
              Jul 26 at 15:07






            • 4




              @tjt263 Yeah, I'd say this might have less educational value than your approach, even though it is a much better way to just generate a random IP address if that's what you really want.
              – David Z
              Jul 26 at 17:46






            • 5




              In CodeReview users aren't trying to do something as efficiently as possible with builtins, but rather get the form of their approach right. Telling someone who's writing an IP generator from scratch to just import it doesn't really serve the community.
              – user1717828
              Jul 26 at 20:42






            • 7




              Before posting it, I considered prefacing my answer with something like "This isn't a proper answer for Code Review, but...", but I didn't think it'd blow up like this. I intended it to be a helpful resource for future people finding this via Google, because just a few months ago, I was in the exact same situation as OP: wanting to write an IP randomizer, not knowing Python could do it for me. I've added a few comments to my examples, hopefully they'll make it more obvious how the code works.
              – Peter W.
              Jul 27 at 6:58






            • 2




              @user1717828 That's not true. If you are open to feedback on CRSE, you are inherently open to alternative solutions to the problem. If you purposefully choose to reinvent the wheel (as a personal challenge or otherwise), there's the reinventing-the-wheel tag.
              – Daniel
              Jul 27 at 23:12














            • 7




              Nice solution - did you consider pushing addr_str = addr.compressed to after the conditional?
              – cmh
              Jul 26 at 15:07






            • 4




              @tjt263 Yeah, I'd say this might have less educational value than your approach, even though it is a much better way to just generate a random IP address if that's what you really want.
              – David Z
              Jul 26 at 17:46






            • 5




              In CodeReview users aren't trying to do something as efficiently as possible with builtins, but rather get the form of their approach right. Telling someone who's writing an IP generator from scratch to just import it doesn't really serve the community.
              – user1717828
              Jul 26 at 20:42






            • 7




              Before posting it, I considered prefacing my answer with something like "This isn't a proper answer for Code Review, but...", but I didn't think it'd blow up like this. I intended it to be a helpful resource for future people finding this via Google, because just a few months ago, I was in the exact same situation as OP: wanting to write an IP randomizer, not knowing Python could do it for me. I've added a few comments to my examples, hopefully they'll make it more obvious how the code works.
              – Peter W.
              Jul 27 at 6:58






            • 2




              @user1717828 That's not true. If you are open to feedback on CRSE, you are inherently open to alternative solutions to the problem. If you purposefully choose to reinvent the wheel (as a personal challenge or otherwise), there's the reinventing-the-wheel tag.
              – Daniel
              Jul 27 at 23:12








            7




            7




            Nice solution - did you consider pushing addr_str = addr.compressed to after the conditional?
            – cmh
            Jul 26 at 15:07




            Nice solution - did you consider pushing addr_str = addr.compressed to after the conditional?
            – cmh
            Jul 26 at 15:07




            4




            4




            @tjt263 Yeah, I'd say this might have less educational value than your approach, even though it is a much better way to just generate a random IP address if that's what you really want.
            – David Z
            Jul 26 at 17:46




            @tjt263 Yeah, I'd say this might have less educational value than your approach, even though it is a much better way to just generate a random IP address if that's what you really want.
            – David Z
            Jul 26 at 17:46




            5




            5




            In CodeReview users aren't trying to do something as efficiently as possible with builtins, but rather get the form of their approach right. Telling someone who's writing an IP generator from scratch to just import it doesn't really serve the community.
            – user1717828
            Jul 26 at 20:42




            In CodeReview users aren't trying to do something as efficiently as possible with builtins, but rather get the form of their approach right. Telling someone who's writing an IP generator from scratch to just import it doesn't really serve the community.
            – user1717828
            Jul 26 at 20:42




            7




            7




            Before posting it, I considered prefacing my answer with something like "This isn't a proper answer for Code Review, but...", but I didn't think it'd blow up like this. I intended it to be a helpful resource for future people finding this via Google, because just a few months ago, I was in the exact same situation as OP: wanting to write an IP randomizer, not knowing Python could do it for me. I've added a few comments to my examples, hopefully they'll make it more obvious how the code works.
            – Peter W.
            Jul 27 at 6:58




            Before posting it, I considered prefacing my answer with something like "This isn't a proper answer for Code Review, but...", but I didn't think it'd blow up like this. I intended it to be a helpful resource for future people finding this via Google, because just a few months ago, I was in the exact same situation as OP: wanting to write an IP randomizer, not knowing Python could do it for me. I've added a few comments to my examples, hopefully they'll make it more obvious how the code works.
            – Peter W.
            Jul 27 at 6:58




            2




            2




            @user1717828 That's not true. If you are open to feedback on CRSE, you are inherently open to alternative solutions to the problem. If you purposefully choose to reinvent the wheel (as a personal challenge or otherwise), there's the reinventing-the-wheel tag.
            – Daniel
            Jul 27 at 23:12




            @user1717828 That's not true. If you are open to feedback on CRSE, you are inherently open to alternative solutions to the problem. If you purposefully choose to reinvent the wheel (as a personal challenge or otherwise), there's the reinventing-the-wheel tag.
            – Daniel
            Jul 27 at 23:12













            25














            Here are a few ideas about your code.



            Check for command line arguments



            The code fails with an exception if it's invoked with no command line arguments because it attempts to use argv[1] and there isn't any. I'd suggest that it would be nice to print a "usage" message if the user enters either an invalid or no argument.



            Use a list comprehension



            List comprehensions are extremely useful and very Pythonic. It's really good to become proficient with them. Here's how to use one to generate a random IPv4 address:



            '.'.join([str(randint(0,255)) for x in range(4)])


            And an IPv6 address is a little trickier because we need hex digits.



            ':'.join([hex(randint(2**16,2**17))[-4:] for x in range(8)])


            That works because randint generates a number in the range 0x10000 to 0x20000 and we then pick off the last four hex digits.






            share|improve this answer





















            • Thanks. That last part's a bit clever. I had a similar idea, but wasn't able to pull it off. The list comprehensions are a nice touch too, just a bit trickier to articulate.
              – tjt263
              Jul 26 at 13:37






            • 3




              you can use 0x10000 and 0x20000 instead of 2**16 and 2**17 for better readability.
              – Mathias Ettinger
              Jul 26 at 13:40






            • 2




              It might be worth mentioning that you don't need the list comprehension to really be a list. It could be a generator instead.
              – David Z
              Jul 26 at 17:48










            • For IPv6, leading zeroes in a group can be omitted, so you don't need that trick, and just do ':'.join(hex(randrange(0x10000))[2:] for x in range(8))
              – Robin
              Jul 27 at 12:38












            • @Robin: it's true, but I like to make it appear consistent. Personally, I prefer PeterW. 's answer. Very elegant!
              – Edward
              Jul 27 at 12:40
















            25














            Here are a few ideas about your code.



            Check for command line arguments



            The code fails with an exception if it's invoked with no command line arguments because it attempts to use argv[1] and there isn't any. I'd suggest that it would be nice to print a "usage" message if the user enters either an invalid or no argument.



            Use a list comprehension



            List comprehensions are extremely useful and very Pythonic. It's really good to become proficient with them. Here's how to use one to generate a random IPv4 address:



            '.'.join([str(randint(0,255)) for x in range(4)])


            And an IPv6 address is a little trickier because we need hex digits.



            ':'.join([hex(randint(2**16,2**17))[-4:] for x in range(8)])


            That works because randint generates a number in the range 0x10000 to 0x20000 and we then pick off the last four hex digits.






            share|improve this answer





















            • Thanks. That last part's a bit clever. I had a similar idea, but wasn't able to pull it off. The list comprehensions are a nice touch too, just a bit trickier to articulate.
              – tjt263
              Jul 26 at 13:37






            • 3




              you can use 0x10000 and 0x20000 instead of 2**16 and 2**17 for better readability.
              – Mathias Ettinger
              Jul 26 at 13:40






            • 2




              It might be worth mentioning that you don't need the list comprehension to really be a list. It could be a generator instead.
              – David Z
              Jul 26 at 17:48










            • For IPv6, leading zeroes in a group can be omitted, so you don't need that trick, and just do ':'.join(hex(randrange(0x10000))[2:] for x in range(8))
              – Robin
              Jul 27 at 12:38












            • @Robin: it's true, but I like to make it appear consistent. Personally, I prefer PeterW. 's answer. Very elegant!
              – Edward
              Jul 27 at 12:40














            25












            25








            25






            Here are a few ideas about your code.



            Check for command line arguments



            The code fails with an exception if it's invoked with no command line arguments because it attempts to use argv[1] and there isn't any. I'd suggest that it would be nice to print a "usage" message if the user enters either an invalid or no argument.



            Use a list comprehension



            List comprehensions are extremely useful and very Pythonic. It's really good to become proficient with them. Here's how to use one to generate a random IPv4 address:



            '.'.join([str(randint(0,255)) for x in range(4)])


            And an IPv6 address is a little trickier because we need hex digits.



            ':'.join([hex(randint(2**16,2**17))[-4:] for x in range(8)])


            That works because randint generates a number in the range 0x10000 to 0x20000 and we then pick off the last four hex digits.






            share|improve this answer












            Here are a few ideas about your code.



            Check for command line arguments



            The code fails with an exception if it's invoked with no command line arguments because it attempts to use argv[1] and there isn't any. I'd suggest that it would be nice to print a "usage" message if the user enters either an invalid or no argument.



            Use a list comprehension



            List comprehensions are extremely useful and very Pythonic. It's really good to become proficient with them. Here's how to use one to generate a random IPv4 address:



            '.'.join([str(randint(0,255)) for x in range(4)])


            And an IPv6 address is a little trickier because we need hex digits.



            ':'.join([hex(randint(2**16,2**17))[-4:] for x in range(8)])


            That works because randint generates a number in the range 0x10000 to 0x20000 and we then pick off the last four hex digits.







            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jul 26 at 12:41









            Edward

            46.2k377209




            46.2k377209












            • Thanks. That last part's a bit clever. I had a similar idea, but wasn't able to pull it off. The list comprehensions are a nice touch too, just a bit trickier to articulate.
              – tjt263
              Jul 26 at 13:37






            • 3




              you can use 0x10000 and 0x20000 instead of 2**16 and 2**17 for better readability.
              – Mathias Ettinger
              Jul 26 at 13:40






            • 2




              It might be worth mentioning that you don't need the list comprehension to really be a list. It could be a generator instead.
              – David Z
              Jul 26 at 17:48










            • For IPv6, leading zeroes in a group can be omitted, so you don't need that trick, and just do ':'.join(hex(randrange(0x10000))[2:] for x in range(8))
              – Robin
              Jul 27 at 12:38












            • @Robin: it's true, but I like to make it appear consistent. Personally, I prefer PeterW. 's answer. Very elegant!
              – Edward
              Jul 27 at 12:40


















            • Thanks. That last part's a bit clever. I had a similar idea, but wasn't able to pull it off. The list comprehensions are a nice touch too, just a bit trickier to articulate.
              – tjt263
              Jul 26 at 13:37






            • 3




              you can use 0x10000 and 0x20000 instead of 2**16 and 2**17 for better readability.
              – Mathias Ettinger
              Jul 26 at 13:40






            • 2




              It might be worth mentioning that you don't need the list comprehension to really be a list. It could be a generator instead.
              – David Z
              Jul 26 at 17:48










            • For IPv6, leading zeroes in a group can be omitted, so you don't need that trick, and just do ':'.join(hex(randrange(0x10000))[2:] for x in range(8))
              – Robin
              Jul 27 at 12:38












            • @Robin: it's true, but I like to make it appear consistent. Personally, I prefer PeterW. 's answer. Very elegant!
              – Edward
              Jul 27 at 12:40
















            Thanks. That last part's a bit clever. I had a similar idea, but wasn't able to pull it off. The list comprehensions are a nice touch too, just a bit trickier to articulate.
            – tjt263
            Jul 26 at 13:37




            Thanks. That last part's a bit clever. I had a similar idea, but wasn't able to pull it off. The list comprehensions are a nice touch too, just a bit trickier to articulate.
            – tjt263
            Jul 26 at 13:37




            3




            3




            you can use 0x10000 and 0x20000 instead of 2**16 and 2**17 for better readability.
            – Mathias Ettinger
            Jul 26 at 13:40




            you can use 0x10000 and 0x20000 instead of 2**16 and 2**17 for better readability.
            – Mathias Ettinger
            Jul 26 at 13:40




            2




            2




            It might be worth mentioning that you don't need the list comprehension to really be a list. It could be a generator instead.
            – David Z
            Jul 26 at 17:48




            It might be worth mentioning that you don't need the list comprehension to really be a list. It could be a generator instead.
            – David Z
            Jul 26 at 17:48












            For IPv6, leading zeroes in a group can be omitted, so you don't need that trick, and just do ':'.join(hex(randrange(0x10000))[2:] for x in range(8))
            – Robin
            Jul 27 at 12:38






            For IPv6, leading zeroes in a group can be omitted, so you don't need that trick, and just do ':'.join(hex(randrange(0x10000))[2:] for x in range(8))
            – Robin
            Jul 27 at 12:38














            @Robin: it's true, but I like to make it appear consistent. Personally, I prefer PeterW. 's answer. Very elegant!
            – Edward
            Jul 27 at 12:40




            @Robin: it's true, but I like to make it appear consistent. Personally, I prefer PeterW. 's answer. Very elegant!
            – Edward
            Jul 27 at 12:40











            19














            For someone not familiar with Python, you have picked pretty good habits. Not everyone uses functions or the if __name__ == '__main__' guard first try.



            That being said, I think it would make more sense to provide 2 functions instead of a single one: random_ipv4 and random_ipv6.



            You could also feed generator expressions to join. They are both faster to process than + for + append and easier to read:



            def random_ipv4():
            return '.'.join(str(randint(0,255)) for _ in range(4))


            def random_ipv6():
            return ':'.join(
            ''.join(choice(hexdigits).lower() for _ in range(4))
            for _ in range(8)
            )


            The only thing left being to properly validate that the input is either 4 or 6:



            if __name__ == '__main__':
            if len(sys.argv) < 2:
            sys.exit('Usage: python random_ip.py VERSION')

            version = sys.argv[1]
            if version == '4':
            print(random_ipv4())
            elif version == '6':
            print(random_ipv6())
            else:
            sys.exit('VERSION should be 4 or 6, not {}'.format(version))





            share|improve this answer





















            • CMIIW, but aren't list comprehension a bit faster than generator comprehension when memory is not an issue?
              – Ludisposed
              Jul 26 at 14:01










            • @Ludisposed Found old timings at bytes.com/topic/python/answers/… But for join it shouldn't matter much as the current implementation convert the input to a list right away.
              – Mathias Ettinger
              Jul 26 at 14:49










            • @Ludisposed My own testing indicates 5.792979179001122 seconds for 1 million calls to random_ipv4 using a generator expression and 5.526552320003248 using a list-comprehension. Nothing really conclusive to prefer one over the other. And since we aren't to re-use the result, a generator expression is a good indication of that.
              – Mathias Ettinger
              Jul 26 at 15:01








            • 1




              Yes it shouldn't matter much and is dependent on the data. I agree with your reasoning for choosing a generator.
              – Ludisposed
              Jul 26 at 15:11
















            19














            For someone not familiar with Python, you have picked pretty good habits. Not everyone uses functions or the if __name__ == '__main__' guard first try.



            That being said, I think it would make more sense to provide 2 functions instead of a single one: random_ipv4 and random_ipv6.



            You could also feed generator expressions to join. They are both faster to process than + for + append and easier to read:



            def random_ipv4():
            return '.'.join(str(randint(0,255)) for _ in range(4))


            def random_ipv6():
            return ':'.join(
            ''.join(choice(hexdigits).lower() for _ in range(4))
            for _ in range(8)
            )


            The only thing left being to properly validate that the input is either 4 or 6:



            if __name__ == '__main__':
            if len(sys.argv) < 2:
            sys.exit('Usage: python random_ip.py VERSION')

            version = sys.argv[1]
            if version == '4':
            print(random_ipv4())
            elif version == '6':
            print(random_ipv6())
            else:
            sys.exit('VERSION should be 4 or 6, not {}'.format(version))





            share|improve this answer





















            • CMIIW, but aren't list comprehension a bit faster than generator comprehension when memory is not an issue?
              – Ludisposed
              Jul 26 at 14:01










            • @Ludisposed Found old timings at bytes.com/topic/python/answers/… But for join it shouldn't matter much as the current implementation convert the input to a list right away.
              – Mathias Ettinger
              Jul 26 at 14:49










            • @Ludisposed My own testing indicates 5.792979179001122 seconds for 1 million calls to random_ipv4 using a generator expression and 5.526552320003248 using a list-comprehension. Nothing really conclusive to prefer one over the other. And since we aren't to re-use the result, a generator expression is a good indication of that.
              – Mathias Ettinger
              Jul 26 at 15:01








            • 1




              Yes it shouldn't matter much and is dependent on the data. I agree with your reasoning for choosing a generator.
              – Ludisposed
              Jul 26 at 15:11














            19












            19








            19






            For someone not familiar with Python, you have picked pretty good habits. Not everyone uses functions or the if __name__ == '__main__' guard first try.



            That being said, I think it would make more sense to provide 2 functions instead of a single one: random_ipv4 and random_ipv6.



            You could also feed generator expressions to join. They are both faster to process than + for + append and easier to read:



            def random_ipv4():
            return '.'.join(str(randint(0,255)) for _ in range(4))


            def random_ipv6():
            return ':'.join(
            ''.join(choice(hexdigits).lower() for _ in range(4))
            for _ in range(8)
            )


            The only thing left being to properly validate that the input is either 4 or 6:



            if __name__ == '__main__':
            if len(sys.argv) < 2:
            sys.exit('Usage: python random_ip.py VERSION')

            version = sys.argv[1]
            if version == '4':
            print(random_ipv4())
            elif version == '6':
            print(random_ipv6())
            else:
            sys.exit('VERSION should be 4 or 6, not {}'.format(version))





            share|improve this answer












            For someone not familiar with Python, you have picked pretty good habits. Not everyone uses functions or the if __name__ == '__main__' guard first try.



            That being said, I think it would make more sense to provide 2 functions instead of a single one: random_ipv4 and random_ipv6.



            You could also feed generator expressions to join. They are both faster to process than + for + append and easier to read:



            def random_ipv4():
            return '.'.join(str(randint(0,255)) for _ in range(4))


            def random_ipv6():
            return ':'.join(
            ''.join(choice(hexdigits).lower() for _ in range(4))
            for _ in range(8)
            )


            The only thing left being to properly validate that the input is either 4 or 6:



            if __name__ == '__main__':
            if len(sys.argv) < 2:
            sys.exit('Usage: python random_ip.py VERSION')

            version = sys.argv[1]
            if version == '4':
            print(random_ipv4())
            elif version == '6':
            print(random_ipv6())
            else:
            sys.exit('VERSION should be 4 or 6, not {}'.format(version))






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jul 26 at 12:48









            Mathias Ettinger

            23.5k33182




            23.5k33182












            • CMIIW, but aren't list comprehension a bit faster than generator comprehension when memory is not an issue?
              – Ludisposed
              Jul 26 at 14:01










            • @Ludisposed Found old timings at bytes.com/topic/python/answers/… But for join it shouldn't matter much as the current implementation convert the input to a list right away.
              – Mathias Ettinger
              Jul 26 at 14:49










            • @Ludisposed My own testing indicates 5.792979179001122 seconds for 1 million calls to random_ipv4 using a generator expression and 5.526552320003248 using a list-comprehension. Nothing really conclusive to prefer one over the other. And since we aren't to re-use the result, a generator expression is a good indication of that.
              – Mathias Ettinger
              Jul 26 at 15:01








            • 1




              Yes it shouldn't matter much and is dependent on the data. I agree with your reasoning for choosing a generator.
              – Ludisposed
              Jul 26 at 15:11


















            • CMIIW, but aren't list comprehension a bit faster than generator comprehension when memory is not an issue?
              – Ludisposed
              Jul 26 at 14:01










            • @Ludisposed Found old timings at bytes.com/topic/python/answers/… But for join it shouldn't matter much as the current implementation convert the input to a list right away.
              – Mathias Ettinger
              Jul 26 at 14:49










            • @Ludisposed My own testing indicates 5.792979179001122 seconds for 1 million calls to random_ipv4 using a generator expression and 5.526552320003248 using a list-comprehension. Nothing really conclusive to prefer one over the other. And since we aren't to re-use the result, a generator expression is a good indication of that.
              – Mathias Ettinger
              Jul 26 at 15:01








            • 1




              Yes it shouldn't matter much and is dependent on the data. I agree with your reasoning for choosing a generator.
              – Ludisposed
              Jul 26 at 15:11
















            CMIIW, but aren't list comprehension a bit faster than generator comprehension when memory is not an issue?
            – Ludisposed
            Jul 26 at 14:01




            CMIIW, but aren't list comprehension a bit faster than generator comprehension when memory is not an issue?
            – Ludisposed
            Jul 26 at 14:01












            @Ludisposed Found old timings at bytes.com/topic/python/answers/… But for join it shouldn't matter much as the current implementation convert the input to a list right away.
            – Mathias Ettinger
            Jul 26 at 14:49




            @Ludisposed Found old timings at bytes.com/topic/python/answers/… But for join it shouldn't matter much as the current implementation convert the input to a list right away.
            – Mathias Ettinger
            Jul 26 at 14:49












            @Ludisposed My own testing indicates 5.792979179001122 seconds for 1 million calls to random_ipv4 using a generator expression and 5.526552320003248 using a list-comprehension. Nothing really conclusive to prefer one over the other. And since we aren't to re-use the result, a generator expression is a good indication of that.
            – Mathias Ettinger
            Jul 26 at 15:01






            @Ludisposed My own testing indicates 5.792979179001122 seconds for 1 million calls to random_ipv4 using a generator expression and 5.526552320003248 using a list-comprehension. Nothing really conclusive to prefer one over the other. And since we aren't to re-use the result, a generator expression is a good indication of that.
            – Mathias Ettinger
            Jul 26 at 15:01






            1




            1




            Yes it shouldn't matter much and is dependent on the data. I agree with your reasoning for choosing a generator.
            – Ludisposed
            Jul 26 at 15:11




            Yes it shouldn't matter much and is dependent on the data. I agree with your reasoning for choosing a generator.
            – Ludisposed
            Jul 26 at 15:11











            14














            Check for invalid outputs, and regenerate them.



            It's possible that you'll produce an output that's reserved for a particular purpose, such as loopback (127.0.0.1 or ::1) or broadcast (255.255.255.255, ff02::1, ff02::2). Build in knowledge of such addresses, and if you find you've produced one, then replace it. You can do that recursively:



            def make_address(v):
            address = random_ip(v)
            if is_reserved(address):
            return make_address(v)
            return address





            share|improve this answer

















            • 2




              There is no need for this to be recursive. It might as well be a while is_reserved(address): loop. But then again, if the chance to generate a valid IP is only a per mille (so you are in danger of regularly hitting the stack size limit), you are probably doing something wrong...
              – Graipher
              Jul 26 at 15:20






            • 1




              Yes, I was just showing one way. Python's only an occasional language for me, and I couldn't remember whether it guarantees tail-call elimination...
              – Toby Speight
              Jul 26 at 16:13










            • Maybe you want extra options to create IPv6 addresses formed from mapping IPv4 addresses and from hardware MAC addresses, then.
              – Toby Speight
              Jul 26 at 16:59








            • 1




              @TobySpeight It doesn't, but there is a way to guarantee it manually, by using a decorator: stackoverflow.com/q/27417874/2415524
              – mbomb007
              Jul 27 at 21:52
















            14














            Check for invalid outputs, and regenerate them.



            It's possible that you'll produce an output that's reserved for a particular purpose, such as loopback (127.0.0.1 or ::1) or broadcast (255.255.255.255, ff02::1, ff02::2). Build in knowledge of such addresses, and if you find you've produced one, then replace it. You can do that recursively:



            def make_address(v):
            address = random_ip(v)
            if is_reserved(address):
            return make_address(v)
            return address





            share|improve this answer

















            • 2




              There is no need for this to be recursive. It might as well be a while is_reserved(address): loop. But then again, if the chance to generate a valid IP is only a per mille (so you are in danger of regularly hitting the stack size limit), you are probably doing something wrong...
              – Graipher
              Jul 26 at 15:20






            • 1




              Yes, I was just showing one way. Python's only an occasional language for me, and I couldn't remember whether it guarantees tail-call elimination...
              – Toby Speight
              Jul 26 at 16:13










            • Maybe you want extra options to create IPv6 addresses formed from mapping IPv4 addresses and from hardware MAC addresses, then.
              – Toby Speight
              Jul 26 at 16:59








            • 1




              @TobySpeight It doesn't, but there is a way to guarantee it manually, by using a decorator: stackoverflow.com/q/27417874/2415524
              – mbomb007
              Jul 27 at 21:52














            14












            14








            14






            Check for invalid outputs, and regenerate them.



            It's possible that you'll produce an output that's reserved for a particular purpose, such as loopback (127.0.0.1 or ::1) or broadcast (255.255.255.255, ff02::1, ff02::2). Build in knowledge of such addresses, and if you find you've produced one, then replace it. You can do that recursively:



            def make_address(v):
            address = random_ip(v)
            if is_reserved(address):
            return make_address(v)
            return address





            share|improve this answer












            Check for invalid outputs, and regenerate them.



            It's possible that you'll produce an output that's reserved for a particular purpose, such as loopback (127.0.0.1 or ::1) or broadcast (255.255.255.255, ff02::1, ff02::2). Build in knowledge of such addresses, and if you find you've produced one, then replace it. You can do that recursively:



            def make_address(v):
            address = random_ip(v)
            if is_reserved(address):
            return make_address(v)
            return address






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jul 26 at 12:50









            Toby Speight

            23.4k639111




            23.4k639111








            • 2




              There is no need for this to be recursive. It might as well be a while is_reserved(address): loop. But then again, if the chance to generate a valid IP is only a per mille (so you are in danger of regularly hitting the stack size limit), you are probably doing something wrong...
              – Graipher
              Jul 26 at 15:20






            • 1




              Yes, I was just showing one way. Python's only an occasional language for me, and I couldn't remember whether it guarantees tail-call elimination...
              – Toby Speight
              Jul 26 at 16:13










            • Maybe you want extra options to create IPv6 addresses formed from mapping IPv4 addresses and from hardware MAC addresses, then.
              – Toby Speight
              Jul 26 at 16:59








            • 1




              @TobySpeight It doesn't, but there is a way to guarantee it manually, by using a decorator: stackoverflow.com/q/27417874/2415524
              – mbomb007
              Jul 27 at 21:52














            • 2




              There is no need for this to be recursive. It might as well be a while is_reserved(address): loop. But then again, if the chance to generate a valid IP is only a per mille (so you are in danger of regularly hitting the stack size limit), you are probably doing something wrong...
              – Graipher
              Jul 26 at 15:20






            • 1




              Yes, I was just showing one way. Python's only an occasional language for me, and I couldn't remember whether it guarantees tail-call elimination...
              – Toby Speight
              Jul 26 at 16:13










            • Maybe you want extra options to create IPv6 addresses formed from mapping IPv4 addresses and from hardware MAC addresses, then.
              – Toby Speight
              Jul 26 at 16:59








            • 1




              @TobySpeight It doesn't, but there is a way to guarantee it manually, by using a decorator: stackoverflow.com/q/27417874/2415524
              – mbomb007
              Jul 27 at 21:52








            2




            2




            There is no need for this to be recursive. It might as well be a while is_reserved(address): loop. But then again, if the chance to generate a valid IP is only a per mille (so you are in danger of regularly hitting the stack size limit), you are probably doing something wrong...
            – Graipher
            Jul 26 at 15:20




            There is no need for this to be recursive. It might as well be a while is_reserved(address): loop. But then again, if the chance to generate a valid IP is only a per mille (so you are in danger of regularly hitting the stack size limit), you are probably doing something wrong...
            – Graipher
            Jul 26 at 15:20




            1




            1




            Yes, I was just showing one way. Python's only an occasional language for me, and I couldn't remember whether it guarantees tail-call elimination...
            – Toby Speight
            Jul 26 at 16:13




            Yes, I was just showing one way. Python's only an occasional language for me, and I couldn't remember whether it guarantees tail-call elimination...
            – Toby Speight
            Jul 26 at 16:13












            Maybe you want extra options to create IPv6 addresses formed from mapping IPv4 addresses and from hardware MAC addresses, then.
            – Toby Speight
            Jul 26 at 16:59






            Maybe you want extra options to create IPv6 addresses formed from mapping IPv4 addresses and from hardware MAC addresses, then.
            – Toby Speight
            Jul 26 at 16:59






            1




            1




            @TobySpeight It doesn't, but there is a way to guarantee it manually, by using a decorator: stackoverflow.com/q/27417874/2415524
            – mbomb007
            Jul 27 at 21:52




            @TobySpeight It doesn't, but there is a way to guarantee it manually, by using a decorator: stackoverflow.com/q/27417874/2415524
            – mbomb007
            Jul 27 at 21:52











            12














            Validate the input: At present, your program




            • aborts with IndexError if called without arguments,

            • aborts with ValueError if called with a non-integer argument,

            • prints None if called with an integer argument that is not 4
              or 6.


            Missing or invalid arguments should print a helpful error message.
            Most Unix command-line tools print the message to the standard error
            and terminate with a non-zero exit status in the case of a failure.



            It would be easier to compare the given argument against the
            strings "4" and "6" instead of converting it to an integer
            (which can fail).





            Use list comprehension instead of appending to an array in a loop.
            Use _ as iterator variable if the concrete value is not needed.



            As an example, the "IPv4" case can be implemented as



            if v == 4:
            return '.'.join(str(randint(0,255)) for _ in range(4))





            share|improve this answer





















            • Why _? Is that a thing people do? I've never seen it before.
              – tjt263
              Jul 26 at 17:45






            • 2




              @tjt263: It is just by convention used as a “throw-away variable,” see for example stackoverflow.com/q/5893163/1187415
              – Martin R
              Jul 26 at 18:27
















            12














            Validate the input: At present, your program




            • aborts with IndexError if called without arguments,

            • aborts with ValueError if called with a non-integer argument,

            • prints None if called with an integer argument that is not 4
              or 6.


            Missing or invalid arguments should print a helpful error message.
            Most Unix command-line tools print the message to the standard error
            and terminate with a non-zero exit status in the case of a failure.



            It would be easier to compare the given argument against the
            strings "4" and "6" instead of converting it to an integer
            (which can fail).





            Use list comprehension instead of appending to an array in a loop.
            Use _ as iterator variable if the concrete value is not needed.



            As an example, the "IPv4" case can be implemented as



            if v == 4:
            return '.'.join(str(randint(0,255)) for _ in range(4))





            share|improve this answer





















            • Why _? Is that a thing people do? I've never seen it before.
              – tjt263
              Jul 26 at 17:45






            • 2




              @tjt263: It is just by convention used as a “throw-away variable,” see for example stackoverflow.com/q/5893163/1187415
              – Martin R
              Jul 26 at 18:27














            12












            12








            12






            Validate the input: At present, your program




            • aborts with IndexError if called without arguments,

            • aborts with ValueError if called with a non-integer argument,

            • prints None if called with an integer argument that is not 4
              or 6.


            Missing or invalid arguments should print a helpful error message.
            Most Unix command-line tools print the message to the standard error
            and terminate with a non-zero exit status in the case of a failure.



            It would be easier to compare the given argument against the
            strings "4" and "6" instead of converting it to an integer
            (which can fail).





            Use list comprehension instead of appending to an array in a loop.
            Use _ as iterator variable if the concrete value is not needed.



            As an example, the "IPv4" case can be implemented as



            if v == 4:
            return '.'.join(str(randint(0,255)) for _ in range(4))





            share|improve this answer












            Validate the input: At present, your program




            • aborts with IndexError if called without arguments,

            • aborts with ValueError if called with a non-integer argument,

            • prints None if called with an integer argument that is not 4
              or 6.


            Missing or invalid arguments should print a helpful error message.
            Most Unix command-line tools print the message to the standard error
            and terminate with a non-zero exit status in the case of a failure.



            It would be easier to compare the given argument against the
            strings "4" and "6" instead of converting it to an integer
            (which can fail).





            Use list comprehension instead of appending to an array in a loop.
            Use _ as iterator variable if the concrete value is not needed.



            As an example, the "IPv4" case can be implemented as



            if v == 4:
            return '.'.join(str(randint(0,255)) for _ in range(4))






            share|improve this answer












            share|improve this answer



            share|improve this answer










            answered Jul 26 at 12:41









            Martin R

            15.5k12264




            15.5k12264












            • Why _? Is that a thing people do? I've never seen it before.
              – tjt263
              Jul 26 at 17:45






            • 2




              @tjt263: It is just by convention used as a “throw-away variable,” see for example stackoverflow.com/q/5893163/1187415
              – Martin R
              Jul 26 at 18:27


















            • Why _? Is that a thing people do? I've never seen it before.
              – tjt263
              Jul 26 at 17:45






            • 2




              @tjt263: It is just by convention used as a “throw-away variable,” see for example stackoverflow.com/q/5893163/1187415
              – Martin R
              Jul 26 at 18:27
















            Why _? Is that a thing people do? I've never seen it before.
            – tjt263
            Jul 26 at 17:45




            Why _? Is that a thing people do? I've never seen it before.
            – tjt263
            Jul 26 at 17:45




            2




            2




            @tjt263: It is just by convention used as a “throw-away variable,” see for example stackoverflow.com/q/5893163/1187415
            – Martin R
            Jul 26 at 18:27




            @tjt263: It is just by convention used as a “throw-away variable,” see for example stackoverflow.com/q/5893163/1187415
            – Martin R
            Jul 26 at 18:27











            7














            Since you already got a couple of answers telling you to validate your inputs, here is a way how to do it using the argparse module:



            import argparse

            if __name__ == "__main__":
            parser = argparse.ArgumentParser()
            parser.add_argument('-v',
            type=int,
            choices=(4, 6),
            default=4,
            help="Whether to generate a random IPv4 or IPv6 address. Default: IPv4.")
            args = parser.parse_args()
            print(random_ip(args.v))


            You can then use it on the command line like this:



            ./randip
            ./randip -v 4
            ./randip -v4
            ./randip -v 6


            If you do anything else, a helpful usage message is printed:



            usage: [-h] [-v {4,6}]

            optional arguments:
            -h, --help show this help message and exit
            -v {4,6} Whether to generate a random IPv4 or IPv6 address. Default:
            IPv4.





            share|improve this answer




























              7














              Since you already got a couple of answers telling you to validate your inputs, here is a way how to do it using the argparse module:



              import argparse

              if __name__ == "__main__":
              parser = argparse.ArgumentParser()
              parser.add_argument('-v',
              type=int,
              choices=(4, 6),
              default=4,
              help="Whether to generate a random IPv4 or IPv6 address. Default: IPv4.")
              args = parser.parse_args()
              print(random_ip(args.v))


              You can then use it on the command line like this:



              ./randip
              ./randip -v 4
              ./randip -v4
              ./randip -v 6


              If you do anything else, a helpful usage message is printed:



              usage: [-h] [-v {4,6}]

              optional arguments:
              -h, --help show this help message and exit
              -v {4,6} Whether to generate a random IPv4 or IPv6 address. Default:
              IPv4.





              share|improve this answer


























                7












                7








                7






                Since you already got a couple of answers telling you to validate your inputs, here is a way how to do it using the argparse module:



                import argparse

                if __name__ == "__main__":
                parser = argparse.ArgumentParser()
                parser.add_argument('-v',
                type=int,
                choices=(4, 6),
                default=4,
                help="Whether to generate a random IPv4 or IPv6 address. Default: IPv4.")
                args = parser.parse_args()
                print(random_ip(args.v))


                You can then use it on the command line like this:



                ./randip
                ./randip -v 4
                ./randip -v4
                ./randip -v 6


                If you do anything else, a helpful usage message is printed:



                usage: [-h] [-v {4,6}]

                optional arguments:
                -h, --help show this help message and exit
                -v {4,6} Whether to generate a random IPv4 or IPv6 address. Default:
                IPv4.





                share|improve this answer














                Since you already got a couple of answers telling you to validate your inputs, here is a way how to do it using the argparse module:



                import argparse

                if __name__ == "__main__":
                parser = argparse.ArgumentParser()
                parser.add_argument('-v',
                type=int,
                choices=(4, 6),
                default=4,
                help="Whether to generate a random IPv4 or IPv6 address. Default: IPv4.")
                args = parser.parse_args()
                print(random_ip(args.v))


                You can then use it on the command line like this:



                ./randip
                ./randip -v 4
                ./randip -v4
                ./randip -v 6


                If you do anything else, a helpful usage message is printed:



                usage: [-h] [-v {4,6}]

                optional arguments:
                -h, --help show this help message and exit
                -v {4,6} Whether to generate a random IPv4 or IPv6 address. Default:
                IPv4.






                share|improve this answer














                share|improve this answer



                share|improve this answer








                edited Jul 26 at 16:47

























                answered Jul 26 at 15:27









                Graipher

                23.5k53585




                23.5k53585






























                    draft saved

                    draft discarded




















































                    Thanks for contributing an answer to Code Review Stack Exchange!


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    Use MathJax to format equations. MathJax reference.


                    To learn more, see our tips on writing great answers.





                    Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                    Please pay close attention to the following guidance:


                    • Please be sure to answer the question. Provide details and share your research!

                    But avoid



                    • Asking for help, clarification, or responding to other answers.

                    • Making statements based on opinion; back them up with references or personal experience.


                    To learn more, see our tips on writing great answers.




                    draft saved


                    draft discarded














                    StackExchange.ready(
                    function () {
                    StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f200337%2frandom-ip-address-generator%23new-answer', 'question_page');
                    }
                    );

                    Post as a guest















                    Required, but never shown





















































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown

































                    Required, but never shown














                    Required, but never shown












                    Required, but never shown







                    Required, but never shown







                    Popular posts from this blog

                    404 Error Contact Form 7 ajax form submitting

                    How to know if a Active Directory user can login interactively

                    TypeError: fit_transform() missing 1 required positional argument: 'X'