All exceptions are a subclass of BaseException, therefore all built-in exceptions should have an args attribute. 
args:
The tuple of arguments given to the exception constructor. Some
  built-in exceptions (like OSError) expect a certain number of
  arguments and assign a special meaning to the elements of this tuple,
  while others are usually called only with a single string giving an
  error message.
The args tuple or string can be provided as the first argument when you raise the exception. 
try:
    raise ZeroDivisionError("error")
except ZeroDivisionError as err:
    print(err)  # prints "error"
The err from except Exception as err: is the Exception instance, when you print(err), you're actually calling the __str__ method of the Exception. Most Exception class's __str__ return's args, since it's the default behaviour of BaseException; __str__ will return otherwise if the exception class override BaseException's __str__. 
When you raised a plain ZeroDivisionError, you provided no args, and ZeroDivisionError does not have a custom __str__ method, therefore it printed args by default, a.k.a args = None.
As for your question:
Isn't an exception came from raise, same as the a general expression?
Yes. They are the same. 
try:
    raise ZeroDivisionError("division by zero")
except ZeroDivisionError as err:
    print(err)       
This will output the same as 1/0.
I went ahead and dig through the source code.  // (integer division) and / (true division) have a slightly different error message. But basically they are defined as such:
if (size_b == 0) {
        PyErr_SetString(PyExc_ZeroDivisionError,
                        "division by zero");
        return -1;
    }
Whereas size_b is the divisor. As you can see, 1/0 or any division by zero raises a ZeroDivsionError with args set as "division by zero" or "integer division or modulo by zero" depending how you divide.