Monday, November 29, 2021

Query Store and hints: More Powerful than ever

I need to confess: I’m proud of the article Query Store and Parameterization Problems I wrote. Today it’s no news at all (although some people may not know the details about plan guides I included in the article) but I wrote it in 2017, based on SQL Server 2016, when the idea of identifying parameter sniffing with query store was very fresh.

Jump to today: Query Store got a new feature, Query Store Hints. This feature is already being the base for many performance improvements in SQL Server. The idea is the possibility to include query hints on the query store queries.

In my article about parameterization, I made use of plan guides exactly because it was the only way to include hints on the queries. Query Store Hints change that, and in my opinion, they make plan guides obsolete. What other reason would make you still use a plan guide today? I would love to hear about it on the comments.

Preparing the Environment

Let’s prepare an environment for some tests.

First Step: Provision a demonstration database

When you are provisioning an Azure SQL Database you can choose to provision a demo database, AdventureWorksLT. Let’s start with one.

Second Step: Creating a view to replate spt_values

We need to make the tables bigger for the example. Many years ago, Adam Machanic created a script called MakeBigAdventure.sql. The script create two tables inside the Adventureworks database, Bigproduct and BigTransactionHistory.

The script was made to work on AdventureWorks in a SQL Server on premises. It uses the table master..spt_values to randomize the records.

On Azure SQL, we don’t have access to the master..spt_values table, so we need to replace it with something else. We can create a view for this purpose. The code of the view will be the following:

CREATE VIEW dbo.spt_values
AS
  WITH int1(z)
       AS (SELECT 0
           UNION ALL
           SELECT 0),
       int2(z)
       AS (SELECT 0
           FROM   int1 a
                  CROSS JOIN int1 b),
       int4(z)
       AS (SELECT 0
           FROM   int2 a
                  CROSS JOIN int2 b),
       int8(z)
       AS (SELECT 0
           FROM   int4 a
                  CROSS JOIN int4 b),
       int16(z)
       AS (SELECT TOP 2048 0
           FROM   int8 a
                  CROSS JOIN int4 b)
  SELECT Cast (NULL AS NVARCHAR(35)) [name],
         Row_number()
           OVER (
             ORDER BY z)  1         AS [number],
         Cast (‘P’ AS NCHAR(3))      [type],
         Cast (NULL AS INT)          [low],
         Cast (NULL AS INT)          [high],
         0                           [status]
  FROM   int16 

Original link: https://devio.wordpress.com/2018/06/03/generating-a-range-of-numbers-and-dates-in-t-sql/

Third Step: Fix the script to work with AdventureWorksLT

AdventureWorks has the schema Product, while AdventureWorksLT has the shema SalesLT. You need to replace the Product schema by SalesLT. A simple find/replace solves the problem.

 

 

Fourth Step: Fix the name of spt_values in the script

A simple replace from master..spt_values to dbo.spt_values will do the work.

Fifth Step: Create an Index

Let’s create an index over a field that we know will have an uneven distribution and due to that will cause the parameter sniffing problem.

You can use the following statement:

CREATE NONCLUSTERED INDEX indprice
  ON [dbo].[BigProduct] ([listprice])

go 

Establishing the problem

This is the same problem describe on the article Query Store and Parameterization Problems, but we will use a different solution.

Let’s create a stored procedure which causes the parameterization problem. The procedure code is below:

CREATE PROCEDURE Filterprice @listprice NUMERIC(15, 2)
AS
    SELECT *
    FROM   dbo.bigproduct
    WHERE  listprice = @listprice 

If you check the estimated execution plan of the code below, you will notice each procedure execution has a different query plan. This happens because the distribution of values in the field is not even. Some values appear way more frequently than others. The use of With Recompile will ensure the plans of these executions will not be stored in the cache

 

EXEC Filterprice
  9.99 WITH recompile
 

EXEC Filterprice
  337.22 WITH recompile 
 

 

Causing the problem

 

The result of the execution of the queries again, without using the With Recompile is both queries will be using the same plan, which will be wrong for one of them.

 

EXEC Filterprice
  9.99

EXEC Filterprice
  337.22 

When one of these procedures is executed without the recompile option, the plan will be included in the query plan cache. The next execution will use the same plan again, causing a problem, because the plan may not be the best choice to the value.

On the original article, we solved the problem using a plan guide to force the recompile of the query. Let’s solve the problem this time using Query Store Hints.

Using Query Store Hints to solve the problem

The Query Store hints are applied over the queries. We need to discover the id of this query inside query store. The following statement can do the work:

SELECT query_sql_text,
       q.query_id
FROM   sys.query_store_query_text qt
       INNER JOIN sys.query_store_query q
               ON qt.query_text_id = q.query_text_id
WHERE  query_sql_text LIKE N’%bigproduct%’
go 

 

Even the query being inside the stored procedure, it will be individually recorded in query store. Once we know the id of the query, we can make the application of the query hint using a stored procedure:

EXEC Sp_query_store_set_hints
  @query_id=1,
  @value = N’OPTION(RECOMPILE)’;

go 

 
Execute the queries again and now each one will have the best plan according the parameter. We also have an additional benefit in comparison to other solutions, such as setting the procedure as WITH RECOMPILE : Only a single query is being recompiled, not the entire procedure.

Monitoring

Once you decide to apply query store hints, there are some monitoring tasks you need to execute:

  • You need to monitor the hints. In case of a failure in a hint, you need to react to that.
  • You need to monitor query regressions. If a hint is not needed anymore, you can suffer from a query regression and this will appear as part of the monitoring.

The following query can be used to monitor the hints:

SELECT query_hint_id,
       query_id,
       query_hint_text,
       last_query_hint_failure_reason,
       last_query_hint_failure_reason_desc,
       query_hint_failure_count,
       source,
       source_desc
FROM   sys.query_store_query_hints;

go 

The Future

SQL Server 2022 is bringing many new optimization features. They are becoming more intelligent and being built over previous existing features. Some of the new optimization features will be automatically creating query store hints.

Conclusion

The SQL Server optimization features are becoming more intelligent on each version. Each new optimization feature, however, brings new and more advanced needs for monitoring.

 

The post Query Store and hints: More Powerful than ever appeared first on Simple Talk.



from Simple Talk https://ift.tt/2ZzeP5s
via

Unity state machine behaviours

An animation in a Unity project is an opportunity to perform many additional actions on top of the animation itself. These actions can be anything the developer desires, including allowing specific user actions or changing variables to your needs. Some time back, Unity’s animation events were demonstrated as a tool for accomplishing some of these goals. They’re great for performing functions at specific points in an animation but not as helpful if there’s something more general you want to do at any point in the animation. Enter Unity State Machine Behaviours, a class of script that works specifically with the Unity Animator system.

Working alongside the Animator, State Machine Behaviours lets you define actions for entering, exiting, and updating various animation states. This means you can have code that runs specifically during an object’s idle state and another script that only executes during the same object’s walking state. Not only does this allow you to perform specific actions during certain states, but it’s also a great way to keep your code organized too. Another great benefit is the ability to reuse these scripts on other state machines, so you don’t have to worry about a script being tied to a single object. As usual, the best way to see the benefits is to see it all in action. Follow along to see how to use these scripts in a project, and by the end, you’ll have a Unity project with a character that performs different actions based on whether it’s in an idle or walking state.

There are many unique assets in this project, so to focus on the code and how it works, a sample project has been created to give you a starting point if you choose to follow along. Additionally, there is a completed version with all the code included to view and modify as you see fit. Links for these projects are listed below. Open the Unity Hub app and click the Add button, find the folder containing the Unity project, and choose Select Folder.

Codeless project: https://github.com/prof-smash/SimpleTalk-StateMachines-Codeless

Complete project: https://github.com/prof-smash/SimpleTalk-StateMachines-Complete

Project overview

First, take a brief look at what’s included in the sample project. Upon opening the project, you should be greeted with a scene with a blue bot character standing on a plane. If you don’t see this, find the SampleScene asset in your Assets window and open it. This blue bot has an animator tied to it that allows playing idle and walking animations. As it walks, it will leave markers on the floor to indicate where it has been. The markers come from the prefab simply named Marker in the Prefabs folder.

Additionally, some text displaying the number of walks the bot has taken is in the upper left corner of the screen. The exact location and appearance of the text may vary depending on your display, so feel free to adjust its position, color, and other properties in the Inspector. Finally, though you can’t see it at the moment, a nav mesh has been set up, which defines the area the bot can walk. If you wish to see this nav mesh, click the Navigation tab in the Inspector area (if you don’t see this tab, go the top menu and choose Window->AI->Navigation), and you should see a blue area in the Scene window that defines the nav mesh. All other assets in the Assets window include the texture for the marker and animations for the bot.

Image showing the project scene with the nav mesh shown. Blue rectangle with a bot.

Figure 1: The project scene with the nav mesh shown

Those animations are brought together via the bot_anim_controller asset in the Animations folder. If you select this asset and open the Animator window (found by going to Window->Animation->Animator), you can see the animator immediately launches the bot into the idle state. If you can’t see this right away, you may need to navigate the Animator window using the Alt key plus mouse button to pan the view. The arrows pointing to and from the idle and walk states are transitions, with each given a condition that must be met for the transition to occur. In this case, two booleans named idle and walk are set to control when the bot is in the idle or walk state, respectively. These two states are where the scripts will be attached to give the bot unique behaviours based on the state.

Image showing bot_anim_controller, showing animation states, transitions, and booleans. Buttons for entry, idle, and walk

Figure 2: bot_anim_controller, showing animation states, transitions, and booleans

If you click on the idle state, you should see a button in the Inspector window that says Add Behaviour. Click this button, then click New Script, then give the script the name IdleStateBehaviour. The newly created script will be immediately added to the idle state, with the asset itself being placed in the Assets folder. Repeat this process for the walk state, this time calling the script WalkStateBehaviour.

Image showing the location of the Add Behaviour button

Figure 3: Adding a new state machine behaviour script

By using this specific button to create the script, Unity will know to make this a script that inherits from the StateMachineBehaviour class, so we won’t have to worry about changing that. It also sets up a template for the state machine behaviour script that gives you all the methods you’ll need to code state behaviours. Double click the IdleStateBehaviour script to open it in Visual Studio and set up the first state behaviour.

IdleStateBehaviour code

As promised, the IdleStateBehaviour script is inheriting from StateMachineBehaviour from the start. Additionally, there are five methods, each with brief documentation of how they work. For this project, the focus will be placed on OnStateEnter, OnStateUpdate, and OnStateExit. As the names imply, these methods perform code based on when the bot enters or exits its idle state and is currently in the idle state. But that’s not all! Like the traditional MonoBehaviour scripts Unity users are used to, you can define variables that can be edited in the Unity editor right here in this script. These variables are a good place to start with the coding process. So, just above OnStateEnter, enter the following:

[Range(2.0f, 10.0f)]
public float waitTime = 5f;
public GameObject marker;
private float timeTillMove = 5f;
private Vector3 stopPosition;

The first two variables will be for you to decide in the editor, with waitTime defining how much time there is between walks. Next is marker, which will be what the bot places down upon leaving its position. Finally, timeTillMove will be the actual timer that counts down between walks, with the time in question coming from waitTime, and stopPosition is the location the bot stops at, which will be used to place markers.

Moving on to OnStateEnter, you’ll notice that an Animator is set in the method’s parameters. In fact, this is true of all the methods in the script. This will be helpful as it allows you easy access to the bot’s animator and the methods and data associated with it. Let’s put it to use along with some additional code:

animator.SetBool("walk", false);
stopPosition = new Vector3(animator.transform.position.x, 
         0.01f, animator.transform.position.z);

Recall the booleans that control when transitions occur in the bot’s animator. When the bot is in its idle state, you wouldn’t want it to start walking in place. To prevent this, set the walk bool in the animator to false the moment the bot enters its idle state. You’ll also go ahead and get its current position for leaving a marker later on when exiting the idle state. The Y value of stopPosition will be set to 0.01 to allow the marker to be slightly above the floor so you can see it. Without this change, the marker will “blend” with the floor and stutter or even be impossible to see.

Let’s move on to OnStateUpdate, which will execute continuously so long as the bot is in its idle state. This method is perfect for counting down the seconds before moving again. To execute this, enter the following:

timeTillMove -= Time.deltaTime;
if (timeTillMove <= 0)
{
        timeTillMove = waitTime;
        animator.SetBool("walk", true);
}

This code is pretty straightforward. The timeTillMove variable is subtracted until it reaches zero, at which point the timer is reset using waitTime, and the walk bool in the animator is set to true. Notice that the timer will not count down until this state is active again, so there’s no need to worry about it counting down too early.

Finally, let’s implement the code for OnStateExit. It consists of a single line that spawns the marker object into the world at the position recorded in stopPosition.

Instantiate(marker, stopPosition, Quaternion.identity);

That’s all the code for IdleStateBehaviour. Now it’s time to move on to the code for the bot’s walk state.

WalkStateBehaviour code

Like the IdleStateBehaviour script, this script will keep its focus on OnStateEnter, OnStateUpdate, and OnStateExit. However, the script as a whole will be slightly more involved than IdleStateBehaviour as it will search for objects in the scene, find a random position for the bot, and update statistics. It will also utilize the UnityEngine.UI and UnityEngine.AI namespaces. With that in mind, let’s set up the using statements now.

using UnityEngine.UI;
using UnityEngine.AI;

Like before, there are also a few variables to declare before getting into the meat of the code, with one of them being a value you’ll set in the editor.

[Range(2.5f, 7f)]

public float maximumWalkingDistance = 4f;

private Text walkText;

private NavMeshAgent agent;

private int walks = 0;

Of particular note, here are the walkText and agent variables. The walkText variable will be given string data to display in the UI seen earlier in the scene. It will be updated with the values of walks whenever the bot has finished taking its short walk. Meanwhile, the agent variable will contain the Nav Mesh Agent component on the bot object. As you’ll see later on, we get the agent by using GetComponent whenever the bot enters the walk state. Why wouldn’t you just set agent in the editor? This is because scripts inheriting from StateMachineBehaviour do not allow you to pass in gameobject data into the script before runtime, including their components. Because the state machine behaviour lives within the animator asset, as opposed to within the scene, we cannot link objects within the scene to the script. Thus, we work around that by using methods like GameObject.Find or reference the gameobject (and thus its components) where the animator is attached.

Next, the code for OnStateEnter:

animator.SetBool(“idle”, false);

walkText = GameObject.Find("WalksText").GetComponent<Text>();
agent = animator.GetComponent<NavMeshAgent>();
agent.destination = RandomPosition(animator.transform.position, 
             maximumWalkingDistance, -1);

First, we make sure the bot cannot accidentally go back to its idle animation while walking. Then you find the WalksText object in the scene and tell the script to use that for walkText. You then set up the NavMeshAgent, including its destination. The destination is found using the RandomPosition, a custom method for finding a random point in the Nav Mesh to walk. Now would be an excellent time to create the RandomPosition method.

Vector3 RandomPosition(Vector3 origin, float distance, int layerMask)
{
        Vector3 randomDirection = Random.insideUnitSphere * distance;
        randomDirection += origin;
        NavMeshHit navHit;
        NavMesh.SamplePosition(randomDirection, out navHit, distance, 
               layerMask);
        return navHit.position;
}

Returning to the pre-generated methods, OnStateUpdate will be utilized to check how far away the bot is from its destination. If it has made it to its destination, then the bot will simply return to the idle state, and the process repeats.

float dist = agent.remainingDistance;
        if (dist != Mathf.Infinity && agent.pathStatus == 
              NavMeshPathStatus.PathComplete && 
               agent.remainingDistance <= 0.01f)
{
            animator.SetBool("idle", true);
}

After leaving this state and returning to the idle state, the number of walks taken is incremented by one. walkText is updated to reflect this change. That code will be going in OnStateExit.

walks++;
walkText.text = "Walks Taken: " + walks.ToString();

That ends all the code needed for this project. Be sure to save all scripts, then return to the Unity editor for some final tasks.

Finishing up

There’s not much else that needs to be done to complete the project. If it’s not open already, make sure the Animator window is open, and you have the bot_anim_controller asset selected. Start by clicking on the idle state. Set the time you want the bot to wait before starting its next walk and make sure the script knows where to find the Marker prefab.

Image showing how to drag the Marker to the Walk state

Figure 4: Assigning the marker

Likewise, select the walk state and set your maximum walking distance. If you only want the bot to take short walks, lower the walking distance. For the opposite, raise the Maximum Walking Distance. Once you’ve made your decision, test out the project using the play button at the top. The bot should start going to random spots on the floor, leaving markers along the way, and counting how many walks it has taken. It will continue to do this until you stop running the project.

Image showing the game in action. The bot is walking and leaving X where it stops.

Figure 5: The project in action

Conclusion

As stated before, the beauty of these scripts is that they can be assigned to any animation state. So you can have multiple objects use the code you’ve just written, even if they have different animators powering them. You just need to be mindful of items like animator booleans and any additional states within the animator. Additionally, these can also be used to give an object specific instructions in an organized, easy to access way. Whether it’s for a simple prototype or a large, complex project, state machine behaviours can be a valuable tool to help you achieve the goals of your Unity project.

As stated before, the beauty of these scripts is that they can be assigned to any animation state. So you can have multiple objects use the code you’ve just written, even if they have different animators powering them. You just need to be mindful of items like animator booleans and any additional states within the animator. Additionally, these can also be used to give an object specific instructions in an organized, easy to access way. Whether it’s for a simple prototype or a large, complex project, state machine behaviours can be a valuable tool to help you achieve the goals of your Unity project.

 

The post Unity state machine behaviours appeared first on Simple Talk.



from Simple Talk https://ift.tt/319lq7v
via

Wednesday, November 24, 2021

Working with PowerShell strings

One of the things that I’ve both appreciated about PowerShell but also been at times confused by PowerShell is its concepts of strings and variables. This article explains what you need to know when working with PowerShell strings.

For example, when you start writing in PowerShell, you may notice that you can use single quotes or double quotes to designate a string.

Starting simple

"A very simple string."
$string1 = "This is a string variable."
$string2 = 'This is also a string variable.'
$string1, $string2
write-host $string1, $string2
write-host $string1 $string2

Save the above as SimpleStrings_demo.ps1. And as usual, examples are available at Github.

When you run the above, you will see the following output:

Image showing output of script. Sometimes, there is a new line

The first line is echoed as is because you haven’t told PowerShell to do anything special.

Then you have created two variables and assigned strings to them. Again, in the case where there’s no assignment and no cmdlet used, PowerShell simply echos out the contents of the variables, one to a line.

When you use the write-host variable, PowerShell will again write them out, but this time keep them on the same line. It doesn’t matter here if you use a comma or not to separate them.

So far, the strings with double quotes and single quotes act the same way. But there is a difference which you’ll see in the following example:

$name = "Greg"
$age = 53
"My name is $name and my age is $age."
$string1 = "DQ: My name is $name and my age is $age."
$string2 = 'SQ: My name is $name and my age is $age.'
write-host $string1
write-host $string2

Save the above as SimpleStrings_with_variables_demo.ps1 and run it.

Your output will look like:

Image showing that variable not replaced in single-quote string

You will immediately notice that in the case of the double quotes, PowerShell did replace the inline variables of $name and $age with their values. However, in the case of single quotes, it treated the variables as part of the string itself and did not replace them.

The upside is that it’s very easy to write out strings with the value of the variables embedded directly in the string. The downside is that you can’t easily print out the variable’s name, which you may want to do while debugging a script.

The following example, SimpleStrings_with_variables_demo_2.ps1 shows a few ways of solving that problem:

$name = "Greg"
$age = 53
"My name is $name and my age is $age."
$string1 = "The `$name value is $name and the `$age value is $age."
$string2 = 'The $name value is ' + $name + ' and the $age value is ' + $age
$string3 = 'The $name value is ' + $name + " and the `$age value is $age"
write-host $string1
write-host $string2
write-host $string3

Image showing other ways to add variable to string

You will notice the backtick character ` allows you to escape the $ so that PowerShell does not treat the characters that follow as a variable name. That is generally the way I do it.

You may be tempted, and it’s perfectly legal, to build a string as shown in $string2, however, I find that harder to read and more complex and see no value to it. $string3 is simply an example showing you can use both single-quoted strings and double-quoted strings when building up a larger string. However, I would definitely avoid that one.

Dealing with objects

You will often find yourself dealing with objects when working with PowerShell. Dealing with objects introduces an issue, but fortunately, like most things, PowerShell has a solution. The following examples can be found in the Github repository in the file Strings_with_object.ps1.

Start by creating an object. For the purposes of this demo, it will be a simple instantiation and assignment.

$person1= @{Name='Greg' 
Age=53}

This object has two properties: a name and an age. Again if you simply hand the object to PowerShell and execute it, PowerShell will print something out, but a bit differently from the above examples.

Pass $person1 to PowerShell and hit enter, and you should see something like:

Image showing tabular results

This method is not terrible, but also not terribly useful. However, if you try to use the write-host cmdlet as follows: write-host $person1, you don’t get what you might expect. Instead, you get the curious response of:

Image showing that printing object shows type not value

That’s not overly helpful. If you try to put the object in between double quotes (since you know with single quotes, it will simply print out what it is handed), you will get the following:

write-host "This is all about $person1"

Image showing that adding $ to object name doesn't print value inside a string

Note the difference in the two responses. In the first case, PowerShell is attempting to parse the object and determine two properties within the object. In the second case, PowerShell doesn’t do any parsing but simply determines it is a hashtable.

The above responses provide the clues you need to get what you want. But before you get there, try the following:

$person1.Name, $person1.Age

You will get:

Image showing you can print object property

This result makes sense because now you are specifying which property you want, but it’s still far from perfect.

You may try the following, which seems like it should work:

write-host "This is all about $person1.Name"

But, curiously, this fails with the following:

Image showing that object variable with property is not replaced in string

Note that this message is a bit different from the above one that mentioned this being a Hashtable. It has .Name appended to the end. It appears that PowerShell is correctly trying to expand the object, but it’s ignoring your reference to a specific property.

The solution here is to force PowerShell to evaluate the entire object before it gets to Write-Host.

You may be tempted to try the following:

# A work around
$personName = $person1.Name
write-host "This is all about $personName"

Executing this will work:

image showing the results of a work around

But, it’s wordy and, in my opinion, a bit messy. Imagine you had an object with a dozen or more properties you wanted to write out.

The solution is to take advantage of scoping and to use parentheses as follows:

write-host "This is all about $($person1.Name) who is $($person1.Age)"

This code will return:

Image showing the result of using parentheses

This result is most likely what you wanted. PowerShell starts with the object inside the parentheses (e.g. $person1.Name) and evaluates that, and then treats it as a variable denoted by the outer $. Write-host then evaluates that variable and inserts it into the string.

Note this means you can do some additional fancy things such as the following

$person2 = @{Name="Joe"
Age=78}
write-host "Together $($person1.Name) and $($person2.Name) are a total of $($person1.Age + $person2.Age) years old."

This will produce:

Image showing summation of values from object

The summation of the ages of $person1 and $person2 happens before Write-host evaluates the outer $.

Formatting strings

Imagine you are tasked with using PowerShell to print out invoices from an order management system. With your newfound knowledge, you sit down and write something like:

$cost = 144.56
$quantity = 11
Write-host "Your cost for $quantity will be: $($cost*$quantity)"

Your output looks like:

Image showing output, cost for 11

It’s not quite perfect. You’d really like to include a currency character to the string, but you can come back to that later.

The more immediate issue is that when $quantity = 10. Then you get the following:

Note the missing trailing 0.

This problem is fortunately easy to fix. PowerShell strings allow formatting using .NET standards.

One simple way of fixing the above is the code below:

$formatted = "Your cost for {0} will be: {1:f2}" -f $quantity, $($quantity*$cost)
write-host $formatted

This will print:

That’s an improvement. The f2 is an instruction to return 2 floating-point values after the period. Additionally, you may want to put a currency symbol in there and a comma.

A simple fix would simply to do the following:

$formatted = "Your cost for {0} will be: `${1:n2}" -f $quantity, $($quantity*$cost)
write-host $formatted

Image showing output with $

Note two essential parts here. The dollar sign was added with a backtick ` so PowerShell doesn’t interpret it as the start of a variable name. In addition, by changing the f to n, PowerShell will treat this as a number using a cultural separator. This code will work equally well in a machine set up in Europe, where they tend to reverse the use of the period and comma separators. However, the currency character is still an issue which can be fixed with slightly different formatting:

$formatted = "Your cost for {0} will be: {1:c2}" -f $quantity, $($quantity*$cost)
write-host $formatted

Image showing output with currency symbol

Note that the $ is no longer needed as part of the string.

PowerShell isn’t just limited to formatting currency; you can use it for other formats. For example, say you needed to generate a list of User IDs with a specific format:

1..15 | % { 'UserID_{0:d4}' -f $_ }

The above will generate 15 User IDs of the format:

Image showing 15 user ids generated

A common requirement is formatting dates. There’s a couple of ways of doing this. If you do nothing and simply accept the defaults as follows:

$exampledate = get-date
write-host $exampledate

The results depend on your regional settings. In the US, you will get:

Image showing date and time

You could format the date when you create it:

$fdate = get-date -Format "yyyy-MM-dd"
write-host $fdate

This will return:

Image showing date only

Unfortunately, the variable $fdate contains only the information shown. You can’t later reference the time if you want.

However, there are a lot of built-in formats available:

$fdate = get-date -Format "R"
write-host $fdate

This method returns:

Image showing date with special formatting

If you want to store the full value of the returned date and later use only a formatted portion of it, you can do something like the following:

write-host $exampledate.ToString('yyyy-MM-dd')
Write-Host $exampledate.ToString("hh:mm:ss")

As you can see, there are plenty of ways to format your strings, dates, and other variables.

String padding and trimming

Often you may find yourself wanting to pad out or trim a string. You may want items to appear clearly in columns on the screen, or you may write to a file with fixed-length fields.

This task can be easily handled, as seen in the examples below. Save these as String_Padding_and_Trimming.ps1.

First, you need to generate some strings. Note that while the first variable claims to have three characters, it actually has a trailing space. This might go unnoticed in some cases if the value was read in from a database field.

$3char = "123 "  # note space!
$4char = "4567"
write-host $3char
Write-Host $4char

This looks perfectly fine as is:

Image showing numbers don't line up on right

# But what if we want them to line up, and we expect someday we might even have longer strings.
$padamount = 5
$padcharacter = ' '
write-host $3char.PadLeft($padamount,$padcharacter)
Write-Host $4char.PadLeft($padamount,$padcharacter)

This now almost works, but that trailing space is obvious:

Image showing numbers don't line up because of trailing space

Fortunately, this is fairly easy to fix using the trim() method:

write-host $3char.trim().PadLeft($padamount,$padcharacter)
Write-Host $4char.PadLeft($padamount,$padcharacter)

Image showing that using trim will align numbers on right

You can also pad to the right and, of course, select other characters. Again notice the trailing space is an issue, so in the second example, you can eliminate it.

$padamount = 7
$padcharacter = '.'
write-host $3char.PadRight($padamount,$padcharacter)
Write-Host $4char.PadRight($padamount,$padcharacter)

Image showing dots with numbers to show where the trailing space is

write-host $3char.trim().PadRight($padamount,$padcharacter)
Write-Host $4char.PadRight($padamount,$padcharacter)

You can do a lot more with the Pad and Trim methods once you fully understand them.

Adding some color to your life

Finally, what is life without some color, or, in this case, showing strings with color?

Like most things, PowerShell makes this very easy. Below is a script that was possibly written by a Hobbit to keep track of something near and dear to their stomach.

Save the following script as String_Color.ps1.

$tod = get-date
if ($tod.Hour -ge 6 -and $tod.Hour -lt 9)
    {
        write-host "Time for Breakfast!" -ForegroundColor Yellow
    }
elseif ($tod.Hour -ge 9 -and $tod.Hour -lt 11)
    {
        write-host "Time for 2nd Breakfast!" -ForegroundColor Red -BackgroundColor Green
        write-host "That's only if he knows about second breakfast!"           
    }    
elseif ($tod.Hour -ge 11 -and $tod.Hour -lt 12)
    {
        write-host "Elevenses!" -BackgroundColor Red
    }    
elseif ($tod.Hour -ge 12 -and $tod.Hour -lt 14)
    {
        write-host "Luncheon" -ForegroundColor Red -BackgroundColor Yellow
    }
else
    {
        Write-host "Afternoon Tea - 2:00 PM until 5:00 PM " -ForegroundColor Black -BackgroundColor DarkRed -NoNewline
        Write-host "Dinner - 7:00 PM until 9:00 PM " -ForegroundColor Red -BackgroundColor DarkBlue -NoNewline
        Write-host "Supper - 9:00 PM until 11:00 PM " -ForegroundColor Red -BackgroundColor DarkGreen
    }

The above script will help any Hobbit keep track of what meal they should be planning for. Note that portion control in case 12 dwarves show up unexpectedly is not covered.

If it’s early in the day, the script will simply change the foreground color of the text to yellow. This color change is done merely by adding the –foreground parameter to write-host.

In the case of second breakfast, you can set both the foreground and background colors as you desire. You will also note that any color you set is only in effect for that particular write-host cmdlet. The following one will revert back to the host colors in your terminal or IDE.

You can, as demonstrated with Elevenses, set only the background color.

Finally, if you want to have multiple colors on the same line, you can take advantage of the –NoNewLine parameter for Write-Host and suppress adding a newline character to your output. This technique can be useful if you want to build a menu option such as below: (save as Select_Option_With_Color.ps1)

write-host "1) " -ForegroundColor Red -NoNewline
write-host "select Option 1" -ForegroundColor Yellow
write-host "2) " -ForegroundColor Red -NoNewline
write-host "select Option 2" -ForegroundColor Yellow
write-host "3) " -ForegroundColor Red -NoNewline
write-host "select Option 3" -ForegroundColor Yellow
$result = Read-host "Select an option above"
if ($result -ge 1 -and $result -le 3)
    { Write-host "Thank you for selecting $result" }
else
    { "You selected an invalid value $result" }

PowerShell strings

In general, string handling in PowerShell is quite simple, but minor differences such as using double quotes or single quotes can make a difference. In addition, knowing how to escape a character or force the evaluation of a variable inside a string can make life simpler as you don’t need to add additional steps before you can output your string.

Additionally, most of the string operations shown in the article can be used when outputting to a file, making the creation of a CSV or file based on length delimited columns far easier to create.

If you like this article, you might also like PowerShell editors and environments part 2.

The post Working with PowerShell strings appeared first on Simple Talk.



from Simple Talk https://ift.tt/3cKsqtH
via

Tuesday, November 23, 2021

Connecting to PostgreSQL: Learning PostgreSQL with Grant

There was a time when most of us worked on a single data platform. Even today, many of us can easily say that we spend the majority of our time on one data platform. However, more of us are moving to manage or develop on, multiple data platforms. I’m right there with you. I have to support and understand many different platforms now. The one I’ve been working with the most is PostgreSQL. Yet, I don’t really feel like I know it very well at all. 

That’s going to change.

I’m going to go on a deeper dive into the PostgreSQL database and bring you along the journey with me. It’s not enough to be able to write a SQL script that works in PostgreSQL. Instead, I want to be able to perform real management, from backups to troubleshooting. Further, I want to develop a database there, with tables, keys, procedures, and all the rest. Finally, I want to be able to monitor and performance tune the queries in PostgreSQL.

That’s the plan.

Now, am I going to go so far as to start writing books on the topic?

No.

However, as I figure things out, I am going to write these blog posts so they can act as a learning guide for others.

If anyone has suggestions, questions, or any feedback at all, please, don’t hesitate to reach out.

Running PostgreSQL

In these wonderful modern times, you really don’t need to install software. Containers and database as a service offerings allow skipping that whole mess. However, if you do want to run PostgreSQL as a service locally, you will need to download PostgreSQL.

Pick the appropriate OS, and then you can download and run the install. Obviously, you can use Chocolatey, HomeBrew, or some other utility for a command line install.

Once you have it installed, you will need to start the service. I’m running Windows 11 at the moment, so I used the following command from a terminal window:

postgres -D ./data

The command means that it’s going to be running in the foreground of that terminal. It’s on the default port, 5432, with the login name ‘postgres’ and whatever password was supplied during the install.

This series of articles uses PostgreSQL on demand, not as a service. That may change down the line, but for now, I’m focusing more on PostgreSQL internal behaviors, not so much about setting it up for a production system.

Using a Docker container to run PostgreSQL is a simple option:

docker pull postgres

That command will get you a PostgreSQL docker image with the latest build, which is, as of this writing, 14.1.1. Running the following will create a container and get things started:

docker run --name PostgreHome -e POSTGRES_PASSWORD=Asecurep@ssw0rd -p 5432:5432 -d postgres

Again, this will run on the default port. If you plan to run multiples of the services or containers, you will need to change the ports.

If all this wasn’t enough, Azure fully supports PostgreSQL database on its excellent data platform. This is configured for you, secure by default, and includes backups as well as a whole host of enhancements. When I’m not running in a container, I’ll probably use this the most for this training.

Finally, AWS offers up two ways to run PostgreSQL. You can use AWS RDS or AWS Aurora. Both run a managed instance of PostgreSQL with many additional bells and whistles like from Azure.

By using one of these four different methods, regardless of your operating system, you should be able to get an instance of PostgreSQL up and running.

Connecting to PostgreSQL

With one of these services running, you next have to connect to PostgreSQL with a tool that will let you run queries. There are a whole slew of them out there. I plan to use Azure Data Studio as my principal tool. I’m picking this because I can easily add my scripts into Github source control, connect to PostgreSQL, and run queries, all from a single location and tool. However, PostgreSQL comes with some tools of its own. Let’s look at those first.

psql

psql is a command-line tool that comes with PostgreSQL. (You can also get it along with the pgAdmin tool discussed in the next section if you didn’t install PostgreSQL locally.) To get started with it, assuming PostgreSQL is in your system path, just do the following:

psql -U postgres

The command starts a psql session, and the user name I wish to log in with is ‘postgres’, the default user. This command assumes I’m running locally through either a container or a service using localhost and the default port. If any of that is not valid, you’ll have to change settings. Hitting enter will bring you to a password prompt. Use the password you used in whichever system you set up above, and you’ll end up at a prompt:

An image showing how to connect to PostgreSQL with psql

There are many commands you can run within psql. For example, to see the databases use the command:

\list

The output will look something like this:

List of databases from PosgreSQL using the \List command

You can then connect to one of those databases like this:

\connect postgrelearning

You’ll then see the prompt has changed to show the different database you’re in:

Image showing how to connect to the postgrelearning database

From there, you’re using SQL within PostgreSQL. Just remember that you must use the semicolon as a statement terminator to make the query run.

pgAdmin

Another tool you can use is pgAdmin, a browser-based tool for working with your PostgreSQL databases. Like with so much else these days, you can download an executable and install it or grab a container. You’ll have to create an account with a password to use this tool. Connecting is the same as anything else; put in the name or the IP address, port, login, and password.

Image showing the pgAdmin tool connection properties

After connecting, you get something that looks like this:

Image showing the pgAdmin tool dashboard and servers

You get some monitoring and other functionality for administering the server and databases. You also get a full query editor:

Image showing the query editor in pgAdmin and a create table statement

You get formatting and some limited code completion. There’s the ability to look at explain plans.

pgAdmin 4 is up to version 6.1. Yeah, I find that confusing too, but that’s what’s going on. It’s a pretty darned complete management tool, even if it’s browser-based.

Azure Data Studio

Azure Data Studio is a multi-platform query tool that currently works with Microsoft SQL Server and PostgreSQL. It’s primarily a development tool for writing queries, although an object explorer lets you look through objects within the database.

To connect to PostgreSQL, you’ll have to install the PostgreSQL extension to Azure Data Studio.

Image showing how to add the PostgreSQL extension for Azure Data Studio

Connections are the same as with the other tools. Fill in the server name or IP, the port if different from the default, user name, and password.

The connection dialog to connect to PosgreSQL from Azure Data Studio

The query editor has good code completion. Running queries looks like this:

Image showing servers on the left and the query editor with code to create a table, populate it with one row and then select. All in Azure Data Studio

Conclusion

I’ve no doubt I’m making some mistakes as I learn this stuff, and I’ll include updates as we go along. This article covered enough to get anyone started within PostgreSQL. From a service, to a container, to a web service, you can run PostgreSQL. Once it’s running, you have multiple tools that can easily connect up to your server or databases. From there, it’s just a question of learning. I’m going to start on the one action I would look to if I were taking on this stuff for a job, backups.

 

The post Connecting to PostgreSQL: Learning PostgreSQL with Grant appeared first on Simple Talk.



from Simple Talk https://ift.tt/3CI025X
via

Monday, November 22, 2021

Dynamic Data Mask is now useful and no one noticed it

Dynamic data mask is a very interesting security feature allowing us to mask critical fields such as e-mail, phone number, credit card and so on. We can decide what users will be able to see the value of these features or not.

This feature faced many flaws when it was released, but I believe it’s stable now, although It’s not the main security feature you should care about, it can still be very useful.

However, until very recently, this feature was not very useful. If you mask many fields in many different tables, the fields may require different permission levels in order to be unmasked.

The only permission control provided for Mask and Unmask fields where this: See everything masked or everything unmasked. In this way, the feature was not useful, because there is not doubt that phone number and credit card should have different permission levels.

Finally, the granular permission control for Data Mask is available in Azure SQL Databases. The feature became way more useful and with so many news around these weeks, not many people noticed.

Test Environment

Let’s test this feature using the AdventureWorksLT. We can provision this database in Azure SQL by choosing to provision a sample database.

Applying the Data Mask

alter table SalesLT.Customer
     alter column EmailAddress nvarchar(50)
        masked with (function=’email()’)
go
alter table SalesLT.Customer
      alter column Phone nvarchar(25)
        masked with(function=‘partial(3,”XXXXXXXXX”,0)’)
go

Create Roles to control Mask Permissions

Control permissions in a field level is something complex. A good practice to do this is using database roles. Let’s create database roles for this and set the permission of these roles as data reader to make the example easier.

Create Role EmailView
go
Create Role PhoneView
go
Alter Role db_datareader add member EmailView
go
Alter Role db_datareader add member PhoneView
go

Grant the unmask peremission

On our example, we will grant the unmask permission over each field for the different database roles. The statements will be like this:

Grant UnMask on SalesLT.Customer(Phone) to PhoneView
go
Grant UnMask on SalesLT.Customer(EmailAddress) to Emailview
go

The granular unmask permission also would allow to grant permission schema level:

Grant UnMask on Schema::SalesLT to CustomRole

Or also on table level:

Grant UnMask on SalesLT.Customer to CustomRole

Anyway, now making the data mask feature really useful.

Create user CanReadEmail with password=‘9646xpahmW’
go
 
Create user CanReadPhone with password=‘9646xpahmW’
go
alter role EmailView add member CanReadEmail
go
alter role PhoneView add member CanReadPhone
go
 

Test the users and UnMask Feature

Execute as user=‘CanReadEmail’
 
select * from SalesLT.Customer
 
revert

This first user can read the phone, but not the e-mail:

 

Execute as user=‘CanReadPhone’
 
select * from SalesLT.Customer
 
revert

This 2nd user can read the e-mail but not the phone:

 

Conclusion

We have a new powerful security feature on our hands to work with and I hope this feature to be in SQL Server 2022 as well

The post Dynamic Data Mask is now useful and no one noticed it appeared first on Simple Talk.



from Simple Talk https://ift.tt/3CAB0Ws
via

Wednesday, November 17, 2021

Mighty Tester – Miracle worker

Image showing a 6 panel strip. Manager ask for a big project that must be perfect and with lots of testing. Then asked that it be done in an hour.

The post Mighty Tester – Miracle worker appeared first on Simple Talk.



from Simple Talk https://ift.tt/3CpAvhK
via

10 reasons why Python is better than C# (or almost any other programming language)

Nearly 10 years ago, I wrote an article on this website comparing C# unfavourably with Visual Basic, which prompted many comments, roughly equally divided between praise and censure. My favourite two (now sadly removed) were “Your website looks like Teletubbieland” (which had some truth at the time, but wasn’t strictly relevant) and “You know f*** all about C#”, which had relevance but – I believe – less truth (and in its original form didn’t have any asterisks either!). To celebrate this anniversary, I’ve decided to reawaken all of you slumbering C# trolls with 10 reasons why Python is better than C# (and better than most other programming languages, too, it has to be said).

1 – Indented code blocks

These are just beautiful! Here’s how you can write a loop and condition in Python to play Fizz-Buzz in Python:

for integer in range(1,11):
    # for first 10 numbers
    if integer % 3 == 0:
        print(integer, "Fizz")
    elif integer % 5 == 0:
        print(integer,"Buzz")

Notice anything? There are no silly { } brackets to denote when a condition or loop block starts and ends because Python can infer this from the indentation. Why type characters when you don’t have to?

2 – Self-declaring Variables

Here’s how you can declare variables in four programming languages:

An image showing how to declare variables in several languages

In Python, you don’t – and can’t – declare variables. Instead, you just assign values to them:

# create a variable to hold the meaning of life
meaning_of_life = 42

Python then creates a variable of the appropriate type (you can prove this by printing out its value):

# show the type of this, and its value
print(type(meaning_of_life),meaning_of_life)

This code would show <class ‘int’> 42. Another nice thing about Python variables is how simple the data types are: there are only integers, floating point numbers, strings, and Boolean values, which is pretty much all a programming language needs, dates being just formatted numbers when all’s said and done).

Now C# programmers will – like I did – initially throw their arms up in horror at this, but haven’t we all been writing lines of code like this for years?

// store life's meaning
var meaningOfLife = 42;

This statement does exactly the same thing: it sets the type of the variable from the context.

I’ve found not having to declare the type of variables strangely liberating, to the extent that I now resent having to declare variables when I go back to writing code in C# or SQL.

3 – Those modules …

Python is Python because of its modules: literally thousands of add-ins, covering everything from scraping websites to advanced AI tasks.

But wait a bit, you may say – C# (at least as it’s written in .NET, which is surely the most common implementation) has “modules” too. Here are just a few of the ones in the System namespace:

An image showing a Using statement in C# and all the options

The answer to which is: yes, it does, but … Python modules are so much easier to use. To illustrate this, let’s take an example: looping over the subfolders in a folder. Here’s how you could do this in Python:

import os
# get a list of all the files in a folder
files = os.listdir(r"C:\__work\\")
# loop over these files
for file in files:
    # show its name
    print(file)

Here’s the approximate equivalent C# code:

using System.IO;
var folder = new DirectoryInfo(@"C:\__work\");
foreach (DirectoryInfo dir in folder.GetDirectories())
{
Debug.WriteLine(dir.Name);
}

I’m aware that it’s subjective, but I find the Python modules to be almost without exception more logically constructed and easier to learn than the equivalent .NET ones, for example.

4 – Simplicity of Data Structures

C# has (deep breath now) the following data structures: Array, ArrayList, Collection, List, Hashtable, Dictionary, SortedDictionary, SortedList. These implement the IEnumerable or IDictionary interfaces. If you’re thinking of learning C#, I’ve probably just put you off for life!

Python has four structures: lists, tuples, dictionaries, and sets, although the first two are virtually identical from the programming point of view. Purists will say that you need all the different data types that C# provides, but trust me, you don’t.

It’s not just that Python only has a few data structures; the ones it does have are so easy to use. Here’s how you create a sorted list of fruit, for example:

# create an empty list
fruit = []
# add some fruit
fruit.append("Pears")
fruit.append("Apples")
fruit.append("Bananas")
# sort this
fruit.sort()
# print

print(fruit)

Programming doesn’t get any more straightforward than this!

5 – Slicing

I’m not generally a fan of languages that try to cram as much logic into as few characters as possible (that’s why I don’t like regular expressions and didn’t get on with Perl).

However, slicing sequences has the big advantage that it’s used everywhere in Python, so once you’ve learnt a few simple rules, you can pick out anything you want. And there’s a certain beauty in code like this:

# the seven deadly sins
sins = ["pride", "envy", "gluttony", "greed", "lust", "sloth", "wrath"]
# every other one, but missing the first and last
# ie ['envy', 'greed', 'sloth']
selected_sins = sins[1:-1:2]
print(selected_sins)

The great thing about slicing is that it carries through to everything. Once you’ve learnt how to slice a tuple, for example, you’ve also learnt how to slice a multi-dimensional array (in numpy) or an Excel-style dataframe (in pandas) or any other sequence of items.

6 – For loops

C# has two separate loop structures, depending on whether you’re looping over numbers or objects, as shown by these two examples:

// first 5 numbers
for (int i=0; i <= 5; i++) {
Debug.Print(i.ToString());
}
// words in a string
string[] words = {"Simple","Talk"};
foreach (string word in words)
{
Debug.Print(word);
}

Here is the same code in Python:

# first 5 numbers
for i in range(1,6):
    print(i)
# words in a string
words = {"Simple","Talk"}
for word in words:
    print(word)

Notice that not only is the Python for loop syntax simple and easier to understand, but there’s only one version of it (unlike in C#, where sometimes you use for and sometimes foreach).

7 – List comprehensions

A list comprehension is one of the most beautiful programming constructs I’ve seen. You can use it as a substitute for C# lambda or anonymous functions, and the result is transparent.

Here’s an example listing out the cubes of all the even numbers up to 10:

# cubes of even numbers up to and including 10
# (would give [8, 64, 216, 512, 1000] as output)
print([n ** 3 for n in range(1,11) if n % 2 == 0])

You could of course do this the long way round:

for n in range(1,11):
    if n % 2 == 0:
        print(n ** 3)

It’s hard to think how you could improve the syntax of the first method: show me this for these numbers where this condition is true.

8 – Sets

I said just now that list comprehensions are beautiful, but so too are sets.

For example, the way to remove duplicates from a list of items in Python is just to convert the list to a set (since sets can’t contain duplicate items, any duplicates will be removed), then convert the set back to a list. Like this, say:

# this contains some duplicates
languages = ["C#","Python","VB","Java","C#","Java","C#"]
# this set can't
language_set = set(languages)
# convert back to a list
languages = list(language_set)
# this will give: ['C#', 'Java', 'Python', 'VB']
print(languages)

However, sets don’t just provide an elegant way to remove duplicates from lists; they also allow you to find the intersection or union of two groups of items (those long-ago maths lessons learning Venn diagrams weren’t wasted after all!).

Pretty much everything you need to know about sets in Python is covered by these few lines of code:

# create two sets: Friends characters and large Antarctic ice shelves
friends = {"Rachel","Phoebe","Chandler", "Joey","Monica","Ross"}
ice_shelves = {"Ronnie-Filchner", "Ross", "McMurdo"}
# show the intersection (elements in both lists)
print(friends & ice_shelves)
# show the union (elements in either list)
print(friends | ice_shelves)
# show the friends who aren't ice shelves
print(friends - ice_shelves)
# elements in either set but not both
print(friends ^ ice_shelves)

This code would give this output ( “Ross” is the only item in both lists, for example):

An images showing the output of sets in Python

9 – Working with files and folders

Virtually everything to do with files and folders is easier than you think it’s going to be. Want to write out the contents of a list? No need to import modules – just do this :

# list of 3 people
people = ["Shadrach","Meshach","Abednego"]
# write them to a file
with open(r"c:\\wiseowl\people.txt","w") as people_file:
    people_file.writelines("\n".join(people))

Want to export this as a CSV file? Just use the built-in csv module:

import csv
# write student amesto a file
with open(r"c:\\wiseowl\students.csv","w",newline="") as people_file:
    potter_file = csv.writer(people_file)
    # use this to write out 3 rows
    potter_file.writerow(["Harry", "Gryffindor"])
    potter_file.writerow(["Draco", "Slytherin"])
    potter_file.writerow(["Hermione", "Gryffindor"])

I could go on to show reading from or writing to JSON files, Excel files, any files using pandas … Python modules make coding as easy as it can be!

10 – The quality of online help

Here are the results of a search using a well-known search engine (!) for the phrase C# tutorial:

An images showing the number of results when searching on C# tutorial

Here are the results for the same search using the phrase Python tutorial:

An image showing the results of searching on Python tutorial

But it’s not just that Python has nearly four times as many tutorial page results: the tutorials themselves are much better, IMHO.

Two reasons not to like Python

It would be disingenuous to end this article without giving two areas in which Python doesn’t compare well with other languages like C#.

The first way in which Python underperforms is that it’s so hard to get started. In C#, you’re probably going to choose Visual Studio as your development environment, and while you will have teething problems, at least everything is integrated. In Python, you have to choose whether to use Visual Studio Code, PyCharm, Jupyter Notebook, or any of a dozen other candidates for your IDE (Integrated Development Environment). Even when you’ve chosen your IDE, you’ll still have to learn how to set up “virtual environments” in which you can install modules for different applications that you’re creating so that they don’t interfere with each other. None of this is straightforward, and it’s a serious impediment to getting started with Python.

The second way in which Python underperforms is that it isn’t always strongly typed. This limitation is best illustrated by an example. Consider this segment of Python code:

def add_numbers(first:int,second:int) -> int:
    # add the two numbers together
    return first + second
# test this out
print(add_numbers(3,5))
# now test this with some text
print(add_numbers("Simple","Talk"))

It creates a function to add two numbers together, then calls it twice. The first call will give 8 (the sum of 3 and 5), while the second will give “SimpleTalk” (treating the “+” in the function as a concatenation symbol).

The problem is this line:

def add_numbers(first:int,second:int) -> int:

This is sometimes referred to as duck typing: if it looks like a duck and quacks like a duck, it’s probably a duck. Except that this looks like an integer and is passed as an integer – and yet is happily accepting a string into the function. The data types are just hints, it turns out: a serious limitation.

Interpreted not compiled

One other big difference between Python and other languages is that the former is interpreted rather than compiled. What this means is that when you run a Python program, the instructions are read as text in sequential order (no executable file is constructed first from the human-readable statements translated into machine-readable language). However, I still can’t decide if this is a good or bad thing, so I have left it off both lists above!

Why Python is better than C#

Python was created by Dutch programmer Guido van Rossum to be as easy to use as possible; he succeeded in his aim! Although the Monty Python references in documentation get a bit tedious (even for this diehard fan), if you’re an experienced C# programmer, you will enjoy the simplicity of programming in Python.

 

If you like this article, you might also like 10 Reasons Why Visual Basic is Better Than C#

 

The post 10 reasons why Python is better than C# (or almost any other programming language) appeared first on Simple Talk.



from Simple Talk https://ift.tt/3Fq3XpF
via