One place for hosting & domains

      Programs

      How to Fix “The Site Ahead Contains Harmful Programs” Warning in WordPress


      WordPress warnings are never pleasant. However, there’s one message that website owners particularly dread: “The site ahead contains harmful programs.”

      Fortunately, this doesn’t have to spell disaster for your website. By following some simple steps, you can remove every trace of this suspicious software.

      In this post, we’ll explore exactly what’s causing the “harmful programs” error. We’ll then show you how to resolve the underlying issue and banish this error message before it can inflict irreversible damage on your search engine rankings. Let’s get started!

      What the Harmful Programs Warning Is (And What It Means)

      If you encounter the “harmful programs” error, then your site has most likely been hacked. In an effort to provide a safe browsing experience, search engines routinely scan the web for digital threats. If they detect malware on your site, they will flag it as unsafe (or label it as a deceptive site) and display a warning to anyone who tries to access your website.

      A Google Chrome search warning.

      Some search engines even display different warning messages based on how your site has been compromised. Depending on the severity of the threat, visitors may get the option to bypass this warning and proceed to your website anyway.

      “The site ahead contains harmful programs” warning.

      When a compromised website appears in the Search Engine Results Pages (SERPs), some engines show an additional warning alongside the site in question. For example, Google’s SERP warnings include “This site may harm your computer and “This site may be hacked.”

      Google’s search engine results warning.

      These security warnings are designed to help keep internet users safe. However, a “harmful programs” message can have several consequences for your site.

      Most website owners see their traffic levels plummet. This will affect your search engine rankings and your conversions. In addition, if your hosting provider discovers that your site has been hacked, they may even suspend your account until you resolve the issue.

      Hacked WordPress Site? We’ll Fix It Fast

      With our Hacked Site Repair service, we’ll fix the malware infection and restore your website so it’s back up and running fast.

      How to Fix the “Site Ahead Contains Harmful Programs Warning” Error in WordPress (In 5 Easy Steps)

      By taking immediate action, you can preserve your SEO success and your site’s reputation as a secure platform. With that in mind, here’s how to remove Google’s “harmful programs” warning message in five easy steps.

      Step 1: Check Your Site Status in Safe Browsing

      Many search engines have built-in mechanisms designed to help keep internet users safe. For example, if Google is warning people away from your site, you might see a huge drop in organic traffic.

      Fortunately, you can verify whether Google has blacklisted your website using the Site Status diagnostic tool.

      Google’s Site Status diagnostic tool.

      Start by entering your WordPress site’s URL. The diagnostic tool will then run its tests and display a warning if it detects any unsafe content.

      If it does warn you about malicious content, your site has been blacklisted. With Google accounting for more than 60% of U.S. desktop search queries, this could have a devastating impact on your traffic. With so much at stake, you must take immediate action to resolve this problem.

      Step 2: Find the Malicious Code

      Once you’ve verified that malicious software is present on your site, it’s time to track down the offending code and files. While it’s possible to look for malware manually, this can be a time-consuming process that often requires a significant amount of technical know-how.

      Hackers are also coming up with new tricks all the time, so it’s not always easy to manually identify every single piece of malicious code. If you do leave some malware behind, search engines may continue to turn visitors away from your site. This means the hack will continue to impact your traffic, conversions, and search engine results.

      If the “harmful programs” warning persists for a significant period of time, it might even inflict long-term damage to your reputation. Your customers may begin to question how seriously you take security and whether you can really be trusted with their personal information.

      With the stakes being so high, we recommend using a professional malware removal service. Our DreamShield add-on can help ensure that your website is free from every trace of malicious code.

      When you add DreamShield to your plan, it will immediately scan your site for malware. It will then repeat this scan automatically every week. If DreamShield detects an issue, it will notify you via email and your DreamHost panel. Thanks to this powerful tool, you may be able to resolve a security breach before Google even realizes there’s a problem!

      To add DreamShield to your account, log in to your DreamHost dashboard. You can then navigate to Domains > Manage Domains.

      DreamHost’s DreamShield service.

      Now, find the domain where you want to enable DreamShield, and click on the accompanying Add Malware Remover link. You can then select the DreamShield Package Remover add-on that you want to use.

      Step 3: Remove the Malware From Your Site

      DreamShield will routinely scan your site and notify you about any issues. These notifications will specify how to remove the detected malware. Simply follow the instructions, and you should be able to eliminate the “harmful programs” warning.

      If you don’t have the DreamSheild add-on, you’ll need to remove these files manually. The best approach will vary, depending on the nature of the hack. However, you can often get positive results by connecting to your site via Secure File Transfer Protocol (SFTP) using a client such as FileZilla.

      Then, carefully work your way through all of your site’s files and delete any that have been compromised.

      A Secure File Transfer Protocol (SFTP) client.

      To speed up the process, it may help to look for files with modification timestamps that occurred around the time of the security breach. You may also want to examine any files where the timestamp seems suspicious, for example, if it’s dated after you last edited your site.

      Some hackers may try to insert code into the .htaccess file. To sanitize this file, connect to your site using an SFTP client. Then navigate to your public_html directory, which contains the .htaccess file.

      WordPress’ .htaccess file.

      Delete this file and then switch over to your WordPress dashboard. You can now navigate to Setting > Permalinks.

      WordPress’ permalink settings.

      Then, simply click on the Save Changes button at the bottom of the page. WordPress will automatically generate a new .htaccess file that’s completely free from malicious code.

      Step 4: Submit Your Site to Google for Review

      Once you’re confident that you’ve removed every trace of malware, you can ask Google to rescan your site. If you haven’t already, you’ll need to sign up to Google Search Console and verify that you own the website in question.

      After claiming your site, log in to the Search Console and navigate to Security & Manual Actions > Security Issues. On the next page, select Request a Review.

      Google will now process your request and provide a response in your Google Webmaster account or your Messages in Search Console. Assuming that you’ve managed to erase all malicious code, Google will remove the “harmful programs” error, and you can resume business as usual.

      Step 5: Harden Your Site Against Future Hacks

      Once you’re back in Google’s good books, it’s smart to perform a security audit. While no website can ever be 100% secure, there are steps you can take to strengthen your site against attack.

      Your password is essential for preventing unauthorized access to your dashboard. However, even with multiple security mechanisms in place, if a hacker manages to guess or steal your password, then all of your hard work may be for nothing.

      To start, it’s always a good idea to follow password best practices. This means using a minimum of eight characters and a mix of upper and lowercase letters, numbers, and symbols. You might also want to consider using a password generator such as Strong Random Password Generator or LastPass.

      The LastPass password generator.

      If you’re using a long and complex password, then you’re off to a great start. However, there are some attacks where password strength has less impact on whether the hacker succeeds or fails. This includes credential stuffing attacks, where a malicious third party attempts to break into your site using dozens or even hundreds of usernames and passwords.

      Two-Factor Authentication (2FA) can make your site far less susceptible to password-based attacks, including credential stuffing. With 2FA in place, a hacker will need to pass an additional security check before they can access your website. For example, they may need to enter a one-time PIN that’s sent to your smartphone.

      We always recommend installing a Secure Sockets Layer certificate (sometimes referred to as an SSL certificate or secure certificate). This ensures that you’re transferring data via Hypertext Transfer Protocol Secure (HTTPS) instead of Hypertext Transfer Protocol (HTTP). When your data is encrypted, it becomes much harder for an attacker to get their hands on information that they can use against you.

      Additional Troubleshooting Tutorials

      Do you want to learn how to resolve other WordPress issues? Here are some of our favorite troubleshooting tutorials:

      If you want more information about keeping your site in tip-top shape, check out our WordPress Tutorials. There, you’ll find everything you need to run a successful website.

      Dealing with Suspicious Code? You Can Skip the Stress

      Avoid troubleshooting unwanted software when you sign up for DreamPress. A friendly WordPress expert is always available 24/7 to help solve your website problems — big or small.

      Fixing the Harmful Programs Error

      If you encounter the “harmful programs” warning when trying to access your site, a hacker may be to blame. While this may sound scary, don’t panic – it is possible to recover a compromised website.

      Let’s quickly recap how to fix the “harmful programs” warning:

      1. First, verify your site status in Safe Browsing.
      2. Find malicious code using a service such as DreamShield.
      3. Remove malware from your site.
      4. Submit your site to Google for review via the Search Console.
      5. Harden your site against future attacks.

      If you’re seeing the “harmful programs” warning, our team of experts can get your site back to normal before the hacker has a chance to do more damage. As part of our Hacked Site Repair Service, we’ll even review your site and upgrade your security at no additional cost.



      Source link

      How To Use argparse to Write Command-Line Programs in Python


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Python’s argparse standard library module is a tool that helps you write command-line interfaces (CLI) over your Python code. You may already be familiar with CLIs: programs like git, ls, grep, and find all expose command-line interfaces that allow you to call an underlying program with specific inputs and options. argparse allows you to call your own custom Python code with command-line arguments similar to how you might invoke git, ls, grep, or find using the command line. You might find this useful if you want to allow other developers to run your code from the command line.

      In this tutorial, you’ll use some of the utilities exposed by Python’s argparse standard library module. You’ll write command-line interfaces that accept positional and optional arguments to control the underlying program’s behavior. You’ll also self-document a CLI by providing help text that can be displayed to other developers who are using your CLI.

      For this tutorial, you’ll write command-line interfaces for a program that keeps track of fish in a fictional aquarium.

      Prerequisites

      To get the most out of this tutorial, we recommend you have:

      • Some familiarity with programming in Python 3. You can review our How To Code in Python 3 tutorial series for background knowledge.

      Writing a Command-Line Program that Accepts a Positional Argument

      You can use the argparse module to write a command-line interface that accepts a positional argument. Positional arguments (as opposed to optional arguments, which we’ll explore in a subsequent section), are generally used to specify required inputs to your program.

      Let’s consider an example CLI that prints the fish in an aquarium tank identified by a positional tank argument.

      To create the CLI, open a file with your text editor:

      Then, add the following Python code:

      aquarium.py

      import argparse
      
      tank_to_fish = {
          "tank_a": "shark, tuna, herring",
          "tank_b": "cod, flounder",
      }
      
      parser = argparse.ArgumentParser(description="List fish in aquarium.")
      parser.add_argument("tank", type=str)
      args = parser.parse_args()
      
      fish = tank_to_fish.get(args.tank, "")
      print(fish)
      

      You can print out the fish in tank_a by running:

      • python3 aquarium.py tank_a

      After running that command, you will receive output like the following:

      Output

      shark, tuna, herring

      Similarly, if you ran aquarium.py to print out the fish in tank_b with:

      • python3 aquarium.py tank_b

      You would receive output like the following:

      Output

      cod, flounder

      Let’s break down the code in aquarium.py.

      First, you import the argparse module to make it available for use in your program. Next, you create a dictionary data structure tank_to_fish that maps tank names (like tank_a and tank_b) to string descriptions of fish held in those tanks.

      You instantiate an instance of the ArgumentParser class and bind it to the parser variable. You can think of parser as the main point of entry for configuring your command-line interface. The description string provided to parser is—as you’ll learn later—used in the automatically generated help text for the CLI exposed by aquarium.py.

      Calling add_argument on parser allows you to add arguments accepted by your command-line interface. In this case, you add a single argument named tank that is a string type. Calling parser.parse_args() instructs parser to process and validate the command-line input passed to aquarium.py (for example, something like tank_a). Accessing the args returned by parser.parse_args() allows you to retrieve the value of the passed in tank argument, and use it to print out the fish in that tank.

      At this point, you’ve written a command-line interface and executed your program to print fish. Now you need to describe how your CLI works to other developers. argparse has strong support for help text to document your CLIs. You’ll learn more about help text next.

      Viewing Help Text

      The aquarium.py file you just wrote in the previous section actually does more than print the fish in a specific tank. Since you’re using argparse, the command-line interface exposed by aquarium.py will automatically include help and usage messages that a user can consult to learn more about your program.

      Consider, for example, the usage message aquarium.py prints if you provide invalid arguments on the command line. Try invoking aquarium.py with the wrong arguments on the command line by running:

      • python3 aquarium.py --not-a-valid-argument

      If you run this command, you’ll receive output like this:

      Output

      usage: aquarium.py [-h] tank aquarium.py: error: the following arguments are required: tank

      The output printed on the command line indicates that there was an error trying to run aquarium.py. The output indicates that the user needs to invoke aquarium.py with a tank argument. Something else you might notice is the -h in-between [] characters. This denotes that -h is an optional argument that you can provide as well.

      Now you’ll find out what happens when you call aquarium.py with the -h option. Try invoking aquarium.py with the -h argument on the command line by running:

      If you run this command, you’ll receive output like this:

      Output

      usage: aquarium.py [-h] tank List fish in aquarium. positional arguments: tank optional arguments: -h, --help show this help message and exit

      As you may have guessed, the -h option is short for, “help.” Running python3 aquarium.py -h (or, equivalently, the longer variant python3 aquarium.py --help) prints out the help text. The help text, effectively, is a longer version of the usage text that was outputted in the previous example when you supplied invalid arguments. Notably, the help text also includes the custom description string of List fish in an aquarium that you instantiated the ArgumentParser with earlier on in this tutorial.

      By default, when you write a CLI using argparse you’ll automatically get help and usage text that you can use to document your CLI for other developers.

      So far, you’ve written a CLI that accepts a required positional argument. In the next section you’ll add an optional argument to your interface to expand on its capabilities.

      Adding an Optional Argument

      Sometimes, it’s helpful to include optional arguments in your command-line interface. These options are typically prefixed with two dash characters, for example --some-option. Let’s rewrite aquarium.py with the following adjusted content that adds an --upper-case option to your CLI:

      aquarium.py

      import argparse
      
      tank_to_fish = {
          "tank_a": "shark, tuna, herring",
          "tank_b": "cod, flounder",
      }
      
      parser = argparse.ArgumentParser(description="List fish in aquarium.")
      parser.add_argument("tank", type=str)
      parser.add_argument("--upper-case", default=False, action="store_true")
      args = parser.parse_args()
      
      fish = tank_to_fish.get(args.tank, "")
      
      if args.upper_case:
          fish = fish.upper()
      
      print(fish)
      

      Try invoking aquarium.py with the new --upper-case argument by running the following:

      • python3 aquarium.py --upper-case tank_a

      If you run this command, you’ll receive output like this:

      Output

      SHARK, TUNA, HERRING

      The fish in tank_a are now outputted in upper case. You accomplished this by adding a new --upper-case option when you called parser.add_argument("--upper-case", default=False, action="store_true"). The "--upper-case" string is the name of the argument you’d like to add.

      If the --upper-case option isn’t provided by the user of the CLI, default=False ensures that its value is set to False by default. action="store_true" controls what happens when the --upper-case option is provided by the CLI user. There are a number of different possible strings supported by the action parameter, but "store_true" stores the value True into the argument, if it is provided on the command line.

      Note that, although the argument is two words separated by a dash (upper-case), argparse makes it available to your code as args.upper_case (with an underscore separator) after you call parser.parse_args(). In general, argparse converts any dashes in the provided arguments into underscores so that you have valid Python identifiers to reference after you call parse_args().

      As before, argparse automatically creates a --help option and documents your command-line interface (including the --upper-case option you just added).

      Try invoking aquarium.py with the --help option again to receive the updated help text:

      • python3 aquarium.py --help

      Your output will be similar to:

      Output

      usage: aquarium.py [-h] [--upper-case] tank List fish in aquarium. positional arguments: tank optional arguments: -h, --help show this help message and exit --upper-case

      argparse automatically documented the positional tank argument, the optional --upper-case option, and the built-in --help option as well.

      This help text is useful, but you can improve it with additional information to help users better understand how they can invoke your program. You’ll explore how to enhance the help text in the next section.

      Exposing Additional Help Text to Your Users

      Developers use the help text provided by your command-line interfaces to understand what your program is capable of and how they should use it. Let’s revise aquarium.py again so it includes better help text. You can specify argument-level information by specifying help strings in the add_argument calls:

      aquarium.py

      import argparse
      
      tank_to_fish = {
          "tank_a": "shark, tuna, herring",
          "tank_b": "cod, flounder",
      }
      
      parser = argparse.ArgumentParser(description="List fish in aquarium.")
      parser.add_argument("tank", type=str, help="Tank to print fish from.")
      parser.add_argument(
          "--upper-case",
          default=False,
          action="store_true",
          help="Upper case the outputted fish.",
      )
      args = parser.parse_args()
      
      fish = tank_to_fish[args.tank]
      
      if args.upper_case:
          fish = fish.upper()
      
      print(fish)
      

      Try invoking aquarium.py with the --help option again to receive the updated help text:

      • python3 aquarium.py --help

      Your output will be the following:

      Output

      usage: aquarium.py [-h] [--upper-case] tank List fish in aquarium. positional arguments: tank Tank to print fish from. optional arguments: -h, --help show this help message and exit --upper-case Upper case the outputted fish.

      In this latest output, notice that the tank positional argument and the --upper-case optional argument both include custom help text. You provided this extra help text by supplying strings to the help part of add_argument. (For example, parser.add_argument("tank", type=str, help="Tank to print fish from.").) argparse takes these strings and renders them for you in the help text output.

      You can improve your help text further by having argparse print out any default values you have defined.

      Displaying Default Values in Help Text

      If you use a custom formatter_class when you instantiate your ArgumentParser instance, argparse will include default values in the help text output. Try adding argparse.ArgumentDefaultsHelpFormatter as your ArgumentParser formatter class:

      aquarium.py

      import argparse
      
      tank_to_fish = {
          "tank_a": "shark, tuna, herring",
          "tank_b": "cod, flounder",
      }
      
      parser = argparse.ArgumentParser(
          description="List fish in aquarium.",
          formatter_class=argparse.ArgumentDefaultsHelpFormatter,
      )
      parser.add_argument("tank", type=str, help="Tank to print fish from.")
      parser.add_argument(
          "--upper-case",
          default=False,
          action="store_true",
          help="Upper case the outputted fish.",
      )
      args = parser.parse_args()
      
      fish = tank_to_fish[args.tank]
      
      if args.upper_case:
          fish = fish.upper()
      
      print(fish)
      

      Now, try invoking aquarium.py with the --help option again to check the updated help text:

      • python3 aquarium.py --help

      After running this command, you’ll receive output like this:

      Output

      usage: aquarium.py [-h] [--upper-case] tank List fish in aquarium. positional arguments: tank Tank to print fish from. optional arguments: -h, --help show this help message and exit --upper-case Upper case the outputted fish. (default: False)

      In this latest output, notice that the documentation for --upper-case ends with an indication of the default value for the --upper-case option (default: False). By including argparse.ArgumentDefaultsHelpFormatter as the formatter_class of your ArgumentParser, argparse automatically started rendering default value information in its help text.

      Conclusion

      The argparse module is a powerful part of the Python standard library that allows you to write command-line interfaces for your code. This tutorial introduced you to the foundations of argparse: you wrote a command-line interface that accepted positional and optional arguments, and exposed help text to the user.

      argparse supports many more feautures that you can use to write command-line programs with sophisticated sets of inputs and validations. From here, you can use the argparse module’s documentation to learn more about other available classes and utilities.



      Source link

      How To Use subprocess to Run External Programs in Python 3


      The author selected the COVID-19 Relief Fund to receive a donation as part of the Write for DOnations program.

      Introduction

      Python 3 includes the subprocess module for running external programs and reading their outputs in your Python code.

      You might find subprocess useful if you want to use another program on your computer from within your Python code. For example, you might want to invoke git from within your Python code to retrieve files in your project that are tracked in git version control. Since any program you can access on your computer can be controlled by subprocess, the examples shown here will be applicable to any external program you might want to invoke from your Python code.

      subprocess includes several classes and functions, but in this tutorial we’ll cover one of subprocess’s most useful functions: subprocess.run. We’ll review its different uses and main keyword arguments.

      Prerequisites

      To get the most out of this tutorial, it is recommended to have some familiarity with programming in Python 3. You can review these tutorials for the necessary background information:

      Running an External Program

      You can use the subprocess.run function to run an external program from your Python code. First, though, you need to import the subprocess and sys modules into your program:

      import subprocess
      import sys
      
      result = subprocess.run([sys.executable, "-c", "print('ocean')"])
      

      If you run this, you will receive output like the following:

      Output

      ocean

      Let’s review this example:

      • sys.executable is the absolute path to the Python executable that your program was originally invoked with. For example, sys.executable might be a path like /usr/local/bin/python.
      • subprocess.run is given a list of strings consisting of the components of the command we are trying to run. Since the first string we pass is sys.executable, we are instructing subprocess.run to execute a new Python program.
      • The -c component is a python command line option that allows you to pass a string with an entire Python program to execute. In our case, we pass a program that prints the string ocean.

      You can think of each entry in the list that we pass to subprocess.run as being separated by a space. For example, [sys.executable, "-c", "print('ocean')"] translates roughly to /usr/local/bin/python -c "print('ocean')". Note that subprocess automatically quotes the components of the command before trying to run them on the underlying operating system so that, for example, you can pass a filename that has spaces in it.

      Warning: Never pass untrusted input to subprocess.run. Since subprocess.run has the ability to perform arbitrary commands on your computer, malicious actors can use it to manipulate your computer in unexpected ways.

      Capturing Output From an External Program

      Now that we can invoke an external program using subprocess.run, let’s see how we can capture output from that program. For example, this process could be useful if we wanted to use git ls-files to output all your files currently stored under version control.

      Note: The examples shown in this section require Python 3.7 or higher. In particular, the capture_output and text keyword arguments were added in Python 3.7 when it was released in June 2018.

      Let’s add to our previous example:

      import subprocess
      import sys
      
      result = subprocess.run(
          [sys.executable, "-c", "print('ocean')"], capture_output=True, text=True
      )
      print("stdout:", result.stdout)
      print("stderr:", result.stderr)
      

      If we run this code, we’ll receive output like the following:

      Output

      stdout: ocean stderr:

      This example is largely the same as the one introduced in the first section: we are still running a subprocess to print ocean. Importantly, however, we pass the capture_output=True and text=True keyword arguments to subprocess.run.

      subprocess.run returns a subprocess.CompletedProcess object that is bound to result. The subprocess.CompletedProcess object includes details about the external program’s exit code and its output. capture_output=True ensures that result.stdout and result.stderr are filled in with the corresponding output from the external program. By default, result.stdout and result.stderr are bound as bytes, but the text=True keyword argument instructs Python to instead decode the bytes into strings.

      In the output section, stdout is ocean (plus the trailing newline that print adds implicitly), and we have no stderr.

      Let’s try an example that produces a non-empty value for stderr:

      import subprocess
      import sys
      
      result = subprocess.run(
          [sys.executable, "-c", "raise ValueError('oops')"], capture_output=True, text=True
      )
      print("stdout:", result.stdout)
      print("stderr:", result.stderr)
      

      If we run this code, we receive output like the following:

      Output

      stdout: stderr: Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: oops

      This code runs a Python subprocess that immediately raises a ValueError. When we inspect the final result, we see nothing in stdout and a Traceback of our ValueError in stderr. This is because by default Python writes the Traceback of the unhandled exception to stderr.

      Raising an Exception on a Bad Exit Code

      Sometimes it’s useful to raise an exception if a program we run exits with a bad exit code. Programs that exit with a zero code are considered successful, but programs that exit with a non-zero code are considered to have encountered an error. As an example, this pattern could be useful if we wanted to raise an exception in the event that we run git ls-files in a directory that wasn’t actually a git repository.

      We can use the check=True keyword argument to subprocess.run to have an exception raised if the external program returns a non-zero exit code:

      import subprocess
      import sys
      
      result = subprocess.run([sys.executable, "-c", "raise ValueError('oops')"], check=True)
      

      If we run this code, we receive output like the following:

      Output

      Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: oops Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.8/subprocess.py", line 512, in run raise CalledProcessError(retcode, process.args, subprocess.CalledProcessError: Command '['/usr/local/bin/python', '-c', "raise ValueError('oops')"]' returned non-zero exit status 1.

      This output shows that we ran a subprocess that raised an error, which is printed in stderr in our terminal. Then subprocess.run dutifully raised a subprocess.CalledProcessError on our behalf in our main Python program.

      Alternatively, the subprocess module also includes the subprocess.CompletedProcess.check_returncode method, which we can invoke for similar effect:

      import subprocess
      import sys
      
      result = subprocess.run([sys.executable, "-c", "raise ValueError('oops')"])
      result.check_returncode()
      

      If we run this code, we’ll receive:

      Output

      Traceback (most recent call last): File "<string>", line 1, in <module> ValueError: oops Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.8/subprocess.py", line 444, in check_returncode raise CalledProcessError(self.returncode, self.args, self.stdout, subprocess.CalledProcessError: Command '['/usr/local/bin/python', '-c', "raise ValueError('oops')"]' returned non-zero exit status 1.

      Since we didn’t pass check=True to subprocess.run, we successfully bound a subprocess.CompletedProcess instance to result even though our program exited with a non-zero code. Calling result.check_returncode(), however, raises a subprocess.CalledProcessError because it detects the completed process exited with a bad code.

      Using timeout to Exit Programs Early

      subprocess.run includes the timeout argument to allow you to stop an external program if it is taking too long to execute:

      import subprocess
      import sys
      
      result = subprocess.run([sys.executable, "-c", "import time; time.sleep(2)"], timeout=1)
      

      If we run this code, we’ll receive output like the following:

      Output

      Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.8/subprocess.py", line 491, in run stdout, stderr = process.communicate(input, timeout=timeout) File "/usr/local/lib/python3.8/subprocess.py", line 1024, in communicate stdout, stderr = self._communicate(input, endtime, timeout) File "/usr/local/lib/python3.8/subprocess.py", line 1892, in _communicate self.wait(timeout=self._remaining_time(endtime)) File "/usr/local/lib/python3.8/subprocess.py", line 1079, in wait return self._wait(timeout=timeout) File "/usr/local/lib/python3.8/subprocess.py", line 1796, in _wait raise TimeoutExpired(self.args, timeout) subprocess.TimeoutExpired: Command '['/usr/local/bin/python', '-c', 'import time; time.sleep(2)']' timed out after 0.9997982999999522 seconds

      The subprocess we tried to run used the time.sleep function to sleep for 2 seconds. However, we passed the timeout=1 keyword argument to subprocess.run to time out our subprocess after 1 second. This explains why our call to subprocess.run ultimately raised a subprocess.TimeoutExpired exception.

      Note that the timeout keyword argument to subprocess.run is approximate. Python will make a best effort to kill the subprocess after the timeout number of seconds, but it won’t necessarily be exact.

      Passing Input to Programs

      Sometimes programs expect input to be passed to them via stdin.

      The input keyword argument to subprocess.run allows you to pass data to the stdin of the subprocess. For example:

      import subprocess
      import sys
      
      result = subprocess.run(
          [sys.executable, "-c", "import sys; print(sys.stdin.read())"], input=b"underwater"
      )
      

      We’ll receive output like the following after running this code:

      Output

      underwater

      In this case, we passed the bytes underwater to input. Our target subprocess used sys.stdin to read the passed in stdin (underwater) and printed it out in our output.

      The input keyword argument can be useful if you want to chain multiple subprocess.run calls together passing the output of one program as the input to another.

      Conclusion

      The subprocess module is a powerful part of the Python standard library that lets you run external programs and inspect their outputs easily. In this tutorial, you have learned to use subprocess.run to control external programs, pass input to them, parse their output, and check their return codes.

      The subprocess module exposes additional classes and utilities that we did not cover in this tutorial. Now that you have a baseline, you can use the subprocess module’s documentation to learn more about other available classes and utilities.



      Source link